javascript可用闭包实现私有观察者模式:通过立即执行函数封装handlers映射表,提供on/emit/off接口;每次调用createobserver()生成独立实例,支持once扩展及错误隔离等优化。

JavaScript 中可以通过闭包封装事件列表和触发逻辑,实现轻量、私有的观察者模式,避免全局污染,同时保证订阅与通知的内部一致性。
用闭包维护私有事件映射表
闭包能将事件名到回调函数数组的映射(如 handlers)封闭在函数作用域内,外部无法直接修改,确保数据安全。只需一个立即执行函数返回操作接口即可:
const createObserver = () => {
const handlers = new Map(); // 键:事件名;值:回调数组
return {
on(event, callback) {
if (!handlers.has(event)) {
handlers.set(event, []);
}
handlers.get(event).push(callback);
},
emit(event, data) {
const callbacks = handlers.get(event) || [];
callbacks.forEach(cb => cb(data));
},
off(event, callback) {
if (!handlers.has(event)) return;
const list = handlers.get(event);
const index = list.indexOf(callback);
if (index > -1) list.splice(index, 1);
}
};
};
实例化后使用,彼此隔离
每次调用 createObserver() 都生成独立的闭包环境,不同实例互不影响。适合模块级或组件级事件管理:
const userEvents = createObserver();
const cartEvents = createObserver();
userEvents.on('login', (user) => console.log('欢迎', user.name));
cartEvents.on('add', (item) => console.log('加入购物车:', item));
userEvents.emit('login', { name: 'Alice' }); // ✅ 输出欢迎信息
cartEvents.emit('add', { id: 101 }); // ✅ 独立触发
// userEvents.emit('add', ...) 不会触发 cartEvents 的回调
支持一次性监听(once)的扩展写法
可在闭包内补充 once 方法:注册时包装回调,执行后自动清理。利用闭包记住原始回调和事件名即可:
// 在 return 对象中添加:
once(event, callback) {
const wrapper = (data) => {
callback(data);
this.off(event, wrapper); // 注意:需确保 this 指向正确,或改用箭头函数 + 显式引用
};
this.on(event, wrapper);
}
更稳妥的做法是把 off 提前绑定,或在闭包内用局部变量保存引用,避免依赖 this。
注意事项与优化点
- 回调执行时若报错,建议用
try/catch包裹单个回调,防止一个失败阻断其余执行 - 可增加
clear(event)清空某事件所有监听,或destroy()彻底释放全部 handler 引用 - 若需异步通知,
emit中可用Promise.all(callbacks.map(cb => Promise.resolve().then(() => cb(data)))) - 不依赖第三方库,纯函数实现,适合嵌入工具函数或小型框架
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











