如何实现继承EventTarget的静态单例类,支持事件监听与触发?
解决方案
首先明确你两种写法报错的原因:
- 第一种写法:
MyClass.dispatchEvent不存在,因为EventTarget的核心方法是实例方法,挂载在EventTarget.prototype上,而MyClass作为构造函数本身并没有继承这些实例方法。 - 第二种写法:
MyClass.prototype只是普通对象,并非EventTarget实例,不符合dispatchEvent对调用上下文的接口要求,因此报错。
要实现「通过构造函数和原型引入EventTarget方法、同时保证单例」的需求,核心思路是让类本身成为EventTarget实例,而非让类的实例继承EventTarget。具体实现如下:
class MyClass extends EventTarget { // 禁止实例化,确保单例特性 constructor() { throw new Error('MyClass 是单例类,请直接使用静态方法'); } // 自定义静态分发方法 static dispatch(type) { // this指向MyClass本身,此时它已经是EventTarget实例 this.dispatchEvent(new Event(type)); } } // 修改类的原型链,让MyClass本身继承EventTarget实例的所有方法 Object.setPrototypeOf(MyClass, new EventTarget()); // 使用示例 MyClass.addEventListener('hello', () => { console.log('hello 事件已触发'); }); MyClass.dispatch('hello'); // 输出: hello 事件已触发
逻辑说明
- 原型链修改:
Object.setPrototypeOf(MyClass, new EventTarget())让MyClass这个构造函数对象直接继承EventTarget实例的方法,因此MyClass本身就具备addEventListener、dispatchEvent、removeEventListener等核心能力。 - 单例保障:构造函数抛出错误,彻底阻止意外实例化的可能,避免多实例导致的事件逻辑混乱。
- 原生方法复用:无需额外定义静态变量存储实例转发方法,直接通过原型链复用
EventTarget的原生实现。
内容的提问来源于stack exchange,提问作者John Leary
相关产品推荐
相关产品推荐

