发布订阅模式
class EventEmitter {
constructor () {
this.events = {};
}
// 绑定函数
on (type, fn) {
(this.events[type] || (this.events[type] = [])).push(fn);
}
// 通知函数执行
emit(type, ...args) {
const callbackArr = this.events[type];
if (!callbackArr || !callbackArr.length) {
return;
}
callbackArr.forEach(callback => {
callback(...args);
});
}
// 解绑
off (type, fn) {
if (!this.events[type]) {
return;
}
if (!fn) {
this.events[type].length = 0;
return;
}
const callbackArr = this.events[type];
if (!callbackArr.length) {
return;
}
let i = callbackArr.length,
callback = null;
while(i--) {
callback = callbackArr[i];
// fn是属性时对应once方法中的fn属性赋值
if (callback === fn || callback.fn === fn) {
callbackArr.splice(i, 1);
break;
}
}
}
// 绑定的函数只会被调用一次
once (type, fn) {
const _this = this;
function on (...args) {
_this.off(type, on);
fn.apply(_this, ...args);
}
// 给解绑时使用
/* 当once绑定的函数一次也没有被调用过,但是fn函数需要被解绑时,
解绑判断使用的就是包装函数on和绑定函数fn的比较结果,此时判定一定不正确。
所以将fn保存起来供解绑时判定使用 */
on.fn = fn;
this.on(type, on);
}
}
参考
发布订阅模式及用户TE_0915
的评论