javascript手写事件总线通过构造函数创建独立事件存储对象,原型链实现on/emit/off方法,支持once和emitasync扩展,适用于跨模块解耦通信。

<p>JavaScript 中手写事件总线(Event Bus),核心是用面向对象封装 + 原型链管理事件监听与触发逻辑,不依赖任何框架,轻量、可复用。</p>
<h3>定义 EventBus 构造函数,初始化事件存储对象</h3>
<p>每个 EventBus 实例应独立维护自己的事件列表(用对象模拟哈希表),键为事件名,值为回调函数数组:</p>
<font color="#666">
<pre class="brush:php;toolbar:false;">
function EventBus() {
this.events = Object.create(null); // 避免原型污染,更干净的空对象
}
在原型上添加 on(订阅)、emit(发布)、off(取消订阅)方法
所有实例共享同一套行为,符合面向对象“行为复用”原则,也体现原型链设计意图:
EventBus.prototype.on = function(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
};
EventBus.prototype.emit = function(event, ...args) {
const callbacks = this.events[event];
if (Array.isArray(callbacks)) {
callbacks.forEach(cb => cb(...args));
}
};
EventBus.prototype.off = function(event, callback) {
const callbacks = this.events[event];
if (Array.isArray(callbacks)) {
if (callback) {
const index = callbacks.indexOf(callback);
if (index > -1) callbacks.splice(index, 1);
} else {
// 不传 callback → 清空该事件所有监听器
this.events[event] = [];
}
}
};
增强实用性:支持 once(一次性监听)和 emitAsync(异步触发)
在原型上扩展常用能力,保持接口统一,不破坏原有结构:
EventBus.prototype.once = function(event, callback) {
const onceWrapper = (...args) => {
callback(...args);
this.off(event, onceWrapper);
};
this.on(event, onceWrapper);
};
EventBus.prototype.emitAsync = async function(event, ...args) {
const callbacks = this.events[event];
if (Array.isArray(callbacks)) {
for (const cb of callbacks) {
await cb(...args);
}
}
};
使用示例:创建实例、跨模块通信
实例化后即可在任意地方导入/引用同一个实例(如单例模式),实现解耦通信:
// 创建全局事件总线(常见做法)
const bus = new EventBus();
// 模块 A 订阅
bus.on('user:login', (user) => console.log('欢迎', user.name));
// 模块 B 发布
bus.emit('user:login', { name: '张三' }); // → 输出:欢迎 张三
// 一次性监听(登录成功后只响一次)
bus.once('api:success', () => console.log('请求成功,仅一次'));
bus.emit('api:success'); // 触发后自动解绑
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











