异步发展流程
高阶函数解决异步问题
发布订阅和观察者模式
Promise核心应用、实现{
主要核心:解决异步问题
}
generator
async + await
AOP
function say(who) {
console.log(who + " is saying...");
};
Function.prototype.before = function() {
console.log('drinking...');
this('macro');
};
say.before();
// 简单应用
Function.prototype.before = function(fn) {
let _this = this;
return function(who) {
fn();
// console.log(this);
console.log(who);
console.log(arguments);
console.log(...arguments); //es6支持展开运算符,把 arguments依次进行展开
_this(...arguments);
// this(); //函数this直接调用是window对象
}
};
let fun = say.before(function() {
console.log('drinking...');
});
fun(['我', '你']);
结果:
drinking...
[ '我', '你' ]
[Arguments] { '0': [ '我', '你' ] }
[ '我', '你' ]
我,你 is saying...
发布订阅
let fs = require('fs');
// 发布订阅:中间代理
// 发布订阅之间没有关系,中间是通过数组进行关联
function Events() {
this.callbacks = [];
this.results = [];
}
//订阅
Events.prototype.on = function(callback) {
this.callbacks.push(callback);
}
//发布
Events.prototype.emit = function(data) {
this.results.push(data);
this.callbacks.forEach(cb => cb(this.results));
}
let e = new Events();
e.on(function(res) {
if (res.length === 2) {
console.log(res);
}
});
//并行操作
fs.readFile('./callback/发布订阅/b.txt', 'utf8', function(err, data) {
e.emit(data);
});
//注意默认路径问题
fs.readFile('./callback/发布订阅/a.txt', 'utf8', function(err, data) {
e.emit(data);
});
观察者模式
//本质是基于观察者模式
//被观察者:
class Subject {
constructor(name) {
this.name = name;
this.observers = []; //所有观察者
this.mood = 'nice';
};
//接受观察者
attach(observer) {
this.observers.push(observer);
};
//
setMood(mood) {
this.mood = mood;
this.observers.forEach(ob => {
ob.update(mood);
});
};
}
//观察者
class Observer {
constructor(name) {
this.name = name;
};
update(mood) {
console.log(this.name + " receive:" + mood);
};
}
let sub = new Subject('girl');
let o1 = new Observer('boy');
let o2 = new Observer('father');
// let o3 = new Observer('boy');
sub.attach(o1);
sub.attach(o2);
sub.setMood("bad");
call() / apply()
在
func
函数运行时使用的this
值。请注意,this
可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为null
或undefined
时会自动替换为指向全局对象,原始值会被包装。call()方法的作用和 apply() 方法类似,区别就是
call()
方法接受的是参数列表,而apply()
方法接受的是一个参数数组/类数组。
toString方法调用与重写
var toString = Object.prototype.toString; toString.call(new Date); // [object Date] toString.call(new String); // [object String] toString.call(Math); // [object Math] //Since JavaScript 1.8.5 toString.call(undefined); // [object Undefined] toString.call(null); // [object Null]
//重写
function Dog(name,breed,color,sex) { this.name = name; this.breed = breed; this.color = color; this.sex = sex; }
Dog.prototype.toString = function dogToString() { var ret = "Dog " + this.name + " is a " + this.sex + " " + this.color + " " + this.breed; return ret; }
// 模板字符串写法
Dog.prototype.toString = function dogToString() { return `Dog ${this.name} is a ${this.sex} ${this.color} ${this.breed}`; }
// 灵活应用
function isType(obj, type) {
console.log(Object.prototype.toString.call(obj));
return Object.prototype.toString.call(obj).includes(type);
}
console.log(isType(arr, 'Array'));
重度灵活:封装使用
let types = ['String', 'Object', 'Array', 'Null', 'Undefined', 'Boolean', 'Function'];
let fns = {};
//返回函数
function isType1(type) {
return function(obj) {
return Object.prototype.toString.call(obj).includes(type);
}
}
types.forEach(type => {
fns['is' + type] = isType1(type);
});
var b = false;
console.log(fns['isString'](b));
console.log(fns['isBoolean'](b));