JavaScript原型本身不支持观察者模式,但可通过构造函数初始化实例私有_events对象,并在原型上定义on/emit/off方法实现事件管理;须避免将_events挂载到原型导致污染,推荐用WeakMap增强内存安全。

JavaScript 中原型对象本身不直接支持观察者模式,但可以通过在原型上定义事件管理方法(如 on、emit、off),让所有实例共享同一套事件机制,从而实现轻量级的观察者通知逻辑。
在原型上统一维护事件监听器
核心思路是把事件映射表(如 _events = {})挂载到原型上,或更稳妥地挂载到每个实例内部(推荐),但注册/触发逻辑放在原型方法中。为避免实例间事件污染,实际开发中通常仍建议在实例初始化时创建独立的事件存储,再通过原型方法操作它:
- 构造函数中为每个实例初始化
this._events = Object.create(null) - 在原型上定义
on(type, handler):将 handler 推入this._events[type]数组 - 定义
emit(type, ...args):遍历this._events[type]并依次调用 - 定义
off(type, handler):从对应数组中移除指定 handler
示例:基于原型的简易 EventEmitter
以下是一个可直接复用的构造函数 + 原型方法组合:
function Observable() {
this._events = Object.create(null);
}
Observable.prototype.on = function(type, handler) {
if (!this._events[type]) this._events[type] = [];
this._events[type].push(handler);
};
Observable.prototype.emit = function(type, ...args) {
const handlers = this._events[type];
if (handlers && handlers.length) {
handlers.forEach(fn => fn(...args));
}
};
Observable.prototype.off = function(type, handler) {
const list = this._events[type];
if (list) {
const i = list.indexOf(handler);
if (i > -1) list.splice(i, 1);
}
};
// 使用
const obj = new Observable();
obj.on('data', (val) => console.log('Received:', val));
obj.emit('data', 'hello'); // 输出:Received: hello
注意原型共享与实例隔离的边界
虽然方法定义在原型上,但 _events 必须是实例私有的。如果错误地把 _events 挂在原型上,所有实例会共用同一份监听器,导致通知混乱:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- ❌ 错误:
Observable.prototype._events = {}→ 所有实例共享事件列表 - ✅ 正确:在构造函数中为
this初始化_events,确保数据隔离 - 可选增强:用
WeakMap存储事件(ES6+),进一步避免内存泄漏和属性暴露
进阶:支持 once、事件命名空间或通配符
可在原型方法中扩展功能,例如:
-
once(type, handler):注册一次性监听器,触发后自动off -
emit('user:login', user)配合on('user:*', cb)实现简单命名空间匹配 - 使用
for...in或正则匹配支持模糊类型(如'data.*')
这些扩展仍基于原型方法封装,不破坏实例数据独立性,同时提升复用性。

















