tiny-emitter
是 Node 提供的 EventEmitter 的简单版本,也就是面试的时候常见的 Emitter 实现
tiny-emitter 的源码就只有一个 index.js
文件
/index.js
(阅读笔记:/index.js/1_structure.js
)function E () {
// Keep this empty so it's easier to inherit from
// (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
}
E.prototype = {
on: function (name, callback, ctx) {},
once: function (name, callback, ctx) {},
emit: function (name) {},
off: function (name, callback) {}
};
module.exports = E;
module.exports.TinyEmitter = E;
一共就实现了四个方法,同时为了保证方便继承,构造函数为空
/index.js
(阅读笔记:/index.js/2_on.js
)E.prototype = {
// ...
on: function (name, callback, ctx) {
var e = this.e || (this.e = {});
(e[name] || (e[name] = [])).push({
fn: callback,
ctx: ctx
});
return this;
},
// ...
};
e
为监听函数对象,保存了 Map<name, listener[]>
的结构,on 方法使用 (e[name] || (e[name] = []))
来保证监听函数列表的存在
/index.js
(阅读笔记:/index.js/3_off.js
)off 稍微复杂一些,一开始先挑出原始的监听队列,并将非目标的监听函数复制到新的队列
E.prototype = {
// ...
off: function (name, callback) {
var e = this.e || (this.e = {});
var evts = e[name];
var liveEvents = [];
if (evts && callback) {
for (var i = 0, len = evts.length; i < len; i++) {
if (evts[i].fn !== callback && evts[i].fn._ !== callback)
liveEvents.push(evts[i]);
}
}
最后检查如果没有监听函数了就释放数组
(liveEvents.length)
? e[name] = liveEvents
: delete e[name];
return this;
}
// ...
};
/index.js
(阅读笔记:/index.js/4_emit.js
)emit 方法先挑出函数列表 evtArr
,并使用 arguments 类数组对象获取参数,最后依次调用
E.prototype = {
// ...
emit: function (name) {
var data = [].slice.call(arguments, 1);
var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
var i = 0;
var len = evtArr.length;
for (i; i < len; i++) {
evtArr[i].fn.apply(evtArr[i].ctx, data);
}
return this;
},
// ...
};
/index.js
(阅读笔记:/index.js/5_once.js
)单次触发的妙用在于,对原函数进行加工成调用后会 off 自己的函数,并将原函数放在 _
属性下,我们可以看到上面的 off 方法就有检查这个 _
属性
E.prototype = {
// ...
once: function (name, callback, ctx) {
var self = this;
function listener () {
self.off(name, listener);
callback.apply(ctx, arguments);
};
listener._ = callback
return this.on(name, listener, ctx);
},
// ...
};
Title | Link |
---|---|
tiny-emitter - npm | https://www.npmjs.com/package/tiny-emitter |
scottcorgan/tiny-emitter - github | https://github.com/scottcorgan/tiny-emitter |
https://github.com/superfreeeee/Blog-code/tree/main/source_code_research/tiny-emitter-2.1.0