观察者模式是一种行为型设计模式,通过主题维护观察者列表并提供订阅、退订、通知方法,实现发布者与订阅者的解耦;典型应用包括DOM事件、状态管理、响应式数据及自定义通信,需注意内存泄漏、循环通知和异步处理。
JavaScript 中的观察者模式是一种行为型设计模式,核心是让多个“观察者”对象监听某个“被观察者”(主题)的状态变化,并在状态改变时自动收到通知并作出响应。它解耦了发布者与订阅者,是前端事件驱动开发的重要思想基础。
不依赖第三方库,可以用类封装主题(Subject)和观察者(Observer)的基本行为:
useEffect 清理函数)中清理示例代码:
class Subject {
constructor() {
this.observers = [];
}
subscribe(observer) {
if (typeof observer === 'function') {
this.observers.push(observer);
}
}
unsubscribe(observer) {
this.observers = this.observers.filter(fn => fn !== observer);
}
notify(data) {
this.observers.forEach(fn => fn(data));
}
}
// 使用
const theme = new Subject();
const logHandler = (msg) => console.log('收到:', msg);
theme.subscribe(logHandler);
theme.notify('按钮被点击了'); // 输出: 收到: 按钮被点击了
它不是只存在于教科书里,而是大量内建于现代前端生态中,常见于以下场景:
addEventListener / dispatchEvent)是最直观的观察者模式体现。元素是主题,事件监听器是观察者store.watch、Redux 的 store.subscribe、Pinia 的 $subscribe 都基于该模式同步状态变更Object.defineProperty 和 Vue 3 的 Proxy 在依赖收集阶段,本质上是为响应式属性建立“主题-观察者”关系(如组件 render 函数作为观察者)观察者模式中,观察者直接订阅具体主题,两者存在引用关系;而发布-订阅模式引入了事件通道(如 Event Emitter),发布者和订阅者完全解耦,只通过事件名通信。前端中:
Node.js EventEmitter、mitt、tiny-emitter 属于发布-订阅watch、React 的 useEffect + 状态依赖),避免重复造轮子useEffect 清理函数),提升可维护性Promise.resolve().then() 或 queueMicrotask 延迟,避免阻塞主线程