如何用class创建EventEmitter类及Movie子类并实现事件触发
实现EventEmitter、Movie子类及Logger类的完整方案
我来帮你一步步搞定这个需求,同时把类继承和事件触发的核心逻辑讲明白,直接上可运行的代码和拆解说明:
1. 先实现核心的EventEmitter基类
这个类需要维护事件与回调的映射,实现constructor初始化、on注册监听,还要补充一个emit方法(触发事件必须用到它,你没提到但不可或缺):
class EventEmitter { constructor() { // 用对象存储每个事件对应的回调函数数组 this.events = {}; } // 注册事件监听:eventName是事件名,callback是要执行的回调 on(eventName, callback) { // 如果事件还没被注册过,先初始化一个空数组 if (!this.events[eventName]) { this.events[eventName] = []; } // 把回调函数加入对应事件的数组 this.events[eventName].push(callback); } // 触发事件:eventName是事件名,...args是传递给回调的参数 emit(eventName, ...args) { // 如果该事件没有注册任何回调,直接返回 if (!this.events[eventName]) return; // 遍历执行该事件下的所有回调 this.events[eventName].forEach(callback => { callback(...args); }); } }
2. 实现Movie子类(继承EventEmitter)
Movie要继承EventEmitter的能力,所以用extends关键字,注意子类构造函数必须先调用super()来初始化父类的属性:
class Movie extends EventEmitter { constructor(title) { // 必须先调用super(),才能访问子类的this super(); this.title = title; // 给Movie加个标题属性,可选 } play() { // 先输出你要的提示信息 console.log(`The 'play' event has been emitted`); // 触发play事件,通知所有注册的监听回调 this.emit('play'); } }
3. 实现Logger类
这个类逻辑很简单,只需要完成constructor初始化和log方法即可:
class Logger { constructor() { // 这里可以加日志级别等初始化逻辑,空实现也没问题 } log(info) { console.log(`Logger: ${info}`); } }
4. 测试代码(实现你要的效果)
把这些类组合起来,测试你给出的场景:
// 创建Logger实例 const logger = new Logger(); // 创建Movie实例(比如《终结者》) const terminator = new Movie('Terminator'); // 给terminator注册play事件的回调,触发时调用logger.log terminator.on('play', () => logger.log('play')); // 调用play方法,触发事件 terminator.play();
运行后会输出:
The 'play' event has been emitted Logger: play
关键疑问解答
关于类继承
- 子类通过
extends关键字继承父类,比如Movie extends EventEmitter,这样Movie就自动拥有了EventEmitter的所有方法(on、emit)和属性(events)。 - 子类的构造函数必须先调用
super(),这会执行父类的构造函数,初始化父类的实例属性,否则子类实例无法访问this,会直接报错。
关于EventEmitter的核心逻辑
on方法是注册事件监听,把回调函数存储到对应事件名的数组里。emit方法是触发事件,遍历对应事件名的回调数组,逐个执行这些回调。- Movie的
play方法里调用this.emit('play'),就是通知所有注册在play事件上的回调函数执行,也就是我们注册的logger.log('play')。
内容的提问来源于stack exchange,提问作者boludo kid
相关产品推荐
相关产品推荐

