// 如果对象中没有对应的 event 值,也就是说明没有订阅过,就给 event 创建个缓存列表
// 如有对象中有相应的 event 值,把 fn 添加到对应 event 的缓存列表里
(_this.list[event] || (_this.list[event] = [])).push(fn);
fn.apply(_this, arguments);
let fns = _this.list[event];
// 如果缓存列表中没有相应的 fn,返回false
// 如果没有传 fn 的话,就会将 event 值对应缓存列表中的 fn 都清空
// 若有 fn,遍历缓存列表,看看传入的 fn 与哪个函数相同,如果相同就直接从缓存列表中删掉即可
for (let i = 0, cbLen = fns.length; i < cbLen; i++) {
if (cb === fn || cb.fn === fn) {
// 第一个参数是对应的 event 值,直接用数组的 shift 方法取出
let event = [].shift.call(arguments),
// 如果缓存列表里没有 fn 就返回 false
if (!fns || fns.length === 0) {
// 遍历 event 值对应的缓存列表,依次执行 fn
fn.apply(_this, arguments);
function user1 (content) {
console.log('用户1订阅了:', content);
function user2 (content) {
console.log('用户2订阅了:', content);
function user3 (content) {
console.log('用户3订阅了:', content);
function user4 (content) {
console.log('用户4订阅了:', content);
eventEmitter.on('article1', user1);
eventEmitter.on('article1', user2);
eventEmitter.on('article1', user3);
eventEmitter.off('article1', user2);
eventEmitter.once('article2', user4)
eventEmitter.emit('article1', 'Javascript 发布-订阅模式');
eventEmitter.emit('article1', 'Javascript 发布-订阅模式');
eventEmitter.emit('article2', 'Javascript 观察者模式');
eventEmitter.emit('article2', 'Javascript 观察者模式');
// eventEmitter.on('article1', user3).emit('article1', 'test111');
用户1订阅了: Javascript 发布-订阅模式
用户3订阅了: Javascript 发布-订阅模式
用户1订阅了: Javascript 发布-订阅模式
用户3订阅了: Javascript 发布-订阅模式