解析MyEventEmitter类emit方法:常量作用与forEach执行逻辑
自定义EventEmitter中emit方法的逻辑解析
一、为什么要创建fireCallbacks常量?
fireCallbacks本质是一个封装了「触发监听函数」逻辑的回调函数——它接收一个已注册的监听函数callback,调用这个函数并把emit传入的data作为参数传递进去。
单独把它抽成常量而非直接写在forEach里,核心是为了提升代码可读性。比如直接写this._events[name].forEach(callback => callback(data))也能实现同样功能,但fireCallbacks这个名字能直接表达「触发回调」的含义,让代码逻辑更直观,尤其是在后续逻辑扩展时,这种命名化的封装能降低阅读和维护成本。
二、forEach是如何调用函数的?
- 首先,
this._events[name]是一个数组,里面存储了所有通过on方法注册到该事件名下的监听函数(比如示例中的handleMyEvent)。 - 数组的
forEach方法会遍历数组中的每一个元素,把当前遍历到的监听函数作为参数,传给fireCallbacks。 - 每一次遍历,
fireCallbacks都会被执行一次,内部会调用传入的监听函数,并把emit的data参数传递过去。
举个实际执行的例子:
当调用myEventEmitter.emit('EventOne', 'hi')时:
this._events['EventOne']数组里存在handleMyEvent函数forEach遍历数组,把handleMyEvent传给fireCallbacksfireCallbacks执行handleMyEvent('hi'),最终打印出Was fired: hi
完整代码示例
class MyEventEmitter { constructor() { this._events = {}; } on(name, listener) { if (!this._events[name]) { this._events[name] = []; } this._events[name].push(listener); } removeListener(name, listenerToRemove) { if (!this._events[name]) { throw new Error(`Can't remove a listener. Event "${name}" doesn't exits.`); } const filterListeners = (listener) => listener !== listenerToRemove; this._events[name] = this._events[name].filter(filterListeners); } emit(name, data) { if (!this._events[name]) { throw new Error(`Can't emit an event. Event "${name}" doesn't exits.`); } const fireCallbacks = (callback) => callback(data); this._events[name].forEach(fireCallbacks); console.log(this._events[name]); } } // 创建实例: const myEventEmitter = new MyEventEmitter(); console.log(myEventEmitter,1); // 创建监听函数: const handleMyEvent = (data) => { console.log('Was fired: ', data); }; console.log(handleMyEvent,2); // 注册监听函数: myEventEmitter.on('EventOne', handleMyEvent); myEventEmitter.on('EventTwo', handleMyEvent); console.log(myEventEmitter); // 触发事件: myEventEmitter.emit('EventOne', 'hi'); myEventEmitter.emit('EventTwo', 'good day!');
内容的提问来源于stack exchange,提问作者Abramo
相关产品推荐
相关产品推荐

