原型继承事件系统需在prototype定义on/emit/off方法,实例通过this._events独立存储监听器,确保隔离性与复用性,支持once、命名空间等增强功能。

在原型继承中实现事件系统,核心是把事件监听和触发逻辑封装到原型链上,让所有实例都能共享这套机制,同时保证每个实例的事件列表相互隔离。
给原型添加 on、emit、off 方法
直接在构造函数的 prototype 上定义事件相关方法,避免每次实例化都重复创建函数。关键点是每个实例需要独立维护自己的事件监听器对象,不能共用同一个 listeners 对象。
- 在构造函数内部初始化 this._events = Object.create(null),确保每个实例有专属监听器存储
- on(type, handler) 把 handler 推入 this._events[type] 数组(需先初始化该 type 的数组)
- emit(type, ...args) 遍历 this._events[type] 并依次调用 handler,支持传参
- off(type, handler) 支持移除指定 handler;若不传 handler,则清空该 type 所有监听器
注意原型链上的 this 指向
所有事件方法必须通过实例调用(如 obj.on(...)),因为方法内部依赖 this._events。如果把方法赋值给变量再调用(如 const fn = obj.on; fn(...)),会丢失 this,导致 this._events 为 undefined。可加一层绑定或用箭头函数包装,但更推荐直接调用。
支持事件订阅/发布解耦
原型事件系统天然适合观察者模式:父类定义事件接口,子类或外部代码按需监听。例如:
- 一个 Component 构造函数提供 on('click', cb) 和 emit('click')
- 子类 Button extends Component 不用重写事件逻辑,直接复用原型上的方法
- 业务代码只关心“什么时机监听”,不关心“谁触发”,实现关注点分离
可选增强:支持 once 和事件命名空间
在基础 on/emit 上扩展,提升实用性:
- once(type, handler):内部调用 on,但在 handler 执行后自动 off 自己
- 事件名支持点号分隔(如 'data.update'),on('data.*', cb) 可匹配所有 data 开头的事件(需额外解析逻辑)
- emit 返回布尔值表示是否有对应监听器,便于判断事件是否被处理











