javascript 事件中心通过闭包封装 events 私有对象,提供 on/emit/off api 实现发布订阅模式,支持 once、错误隔离、自动清理等增强特性,需注意内存泄漏风险。

JavaScript 中可以用闭包封装事件监听器和触发逻辑,避免全局污染,同时保持订阅者与发布者解耦。核心是用一个私有对象存储事件名与回调函数数组的映射关系,所有操作通过返回的公共 API 进行。
定义事件中心结构
闭包内维护一个 events 对象,键为事件名(字符串),值为回调函数数组。外部无法直接访问该对象,只能通过返回的方法操作:
- on(eventName, callback):订阅事件,把回调加入对应数组
- emit(eventName, ...args):发布事件,遍历并执行该事件的所有回调
- off(eventName, callback):取消订阅,从数组中移除指定回调(可选:不传 callback 则清空整个事件)
基础实现示例
以下是一个轻量、可复用的事件中心工厂函数:
function createEventCenter() {
const events = {};
return {
on(event, callback) {
if (!events[event]) events[event] = [];
events[event].push(callback);
},
emit(event, ...args) {
if (events[event]) {
events[event].forEach(cb => cb(...args));
}
},
off(event, callback) {
if (!events[event]) return;
if (!callback) {
events[event] = [];
} else {
events[event] = events[event].filter(cb => cb !== callback);
}
}
};
}
使用方式:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const bus = createEventCenter();
bus.on('login', (user) => console.log('欢迎', user.name));
bus.on('logout', () => console.log('已退出'));
bus.emit('login', { name: 'Alice' }); // 欢迎 Alice
bus.emit('logout'); // 已退出
增强健壮性的小优化
实际项目中可补充几点细节提升可靠性:
- 支持一次触发只执行一次的 once 方法(内部自动在执行后调用 off)
- emit 时对回调执行做 try-catch,防止单个错误中断其余回调
- 增加 clear(event?) 方法,方便测试或重置状态
- 避免重复添加相同回调(可用 WeakMap 或比对引用,但通常由使用者保证)
注意闭包带来的内存管理
闭包会持续持有 events 引用,只要事件中心实例存在,所有已订阅的回调都不会被 GC 回收。如果订阅者是临时对象(比如组件实例),务必在销毁前调用 off,否则可能引发内存泄漏:
// Vue 或 React 组件卸载时
componentWillUnmount() {
bus.off('dataUpdate', this.handleUpdate);
}
也可以设计自动清理机制,比如让 on 返回一个取消函数:
on(event, callback) {
if (!events[event]) events[event] = [];
events[event].push(callback);
return () => this.off(event, callback);
}
// 使用
const unwatch = bus.on('change', handler);
// later
unwatch(); // 等价于 bus.off('change', handler)
不复杂但容易忽略Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










