javascript发布订阅模式核心是维护事件中心,支持subscribe、publish、unsubscribe;基础版用对象映射事件与回调数组,增强版扩展once、offall、onany;需注意匿名函数无法取消、this丢失及内存泄漏问题。

JavaScript 中实现发布订阅模式,核心是维护一个事件中心(事件映射表),支持注册监听器(订阅)、触发通知(发布)和移除监听器(取消订阅)。不需要依赖第三方库,几行代码就能搞定。
基础版:用对象存储事件回调
用一个对象 events 保存事件名到回调函数数组的映射:
- subscribe(event, callback):将回调加入对应事件的数组
- publish(event, ...args):遍历并执行该事件所有回调,传入参数
- unsubscribe(event, callback):从数组中移除指定回调(注意要支持精确匹配)
示例代码:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
class EventEmitter {
constructor() {
this.events = {};
}
subscribe(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
publish(event, ...args) {
const callbacks = this.events[event];
if (callbacks && callbacks.length) {
callbacks.forEach(cb => cb(...args));
}
}
unsubscribe(event, callback) {
const callbacks = this.events[event];
if (callbacks) {
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
}
}
}
// 使用示例
const ee = new EventEmitter();
ee.subscribe('userLogin', (user) => console.log('欢迎', user.name));
ee.subscribe('userLogin', (user) => alert(`登录成功:${user.id}`));
ee.publish('userLogin', { name: '张三', id: 1001 }); // 触发两个回调
ee.unsubscribe('userLogin', (user) => console.log('欢迎', user.name)); // 移除第一个
增强版:支持一次性事件和通配符
实际项目中常需要:once(只执行一次)、offAll(清空某事件所有监听)、onAny(监听所有事件)。可扩展如下:
- 添加
once(event, callback):内部用包装函数,在执行后自动调用unsubscribe - 添加
off(event):直接清空this.events[event] - 添加
onAny(callback):把回调存在特殊键如'*',并在publish时一并触发
注意事项:避免内存泄漏和 this 丢失
使用时容易踩坑:
- 匿名函数无法被
unsubscribe—— 订阅和取消必须用同一个函数引用 - 类方法作为回调时,
this可能丢失 —— 推荐用箭头函数或提前bind - 长期运行的页面中,未及时
unsubscribe会导致监听器堆积 —— 组件销毁时记得清理
现代替代方案:考虑用 Proxy 或 Map 提升健壮性
用 Map 替代普通对象可避免原型链干扰(如 event 名为 toString);用 WeakMap 存储私有事件数据可辅助自动回收。但对简单场景,对象已足够轻量可靠。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










