响应式系统通过proxy或object.defineproperty拦截属性读写,结合依赖收集(dep)与副作用触发(effect),实现数据变化自动更新视图。

可以通过重写对象的 getter 和 setter,配合依赖收集与通知机制,让属性访问自动触发观察者更新。核心是拦截读写行为,而非仅靠手动调用方法。
使用 Proxy 拦截属性操作
Proxy 是现代 JavaScript 中最直接的方式,能统一拦截对象所有属性的读写、删除等操作,无需逐个定义 getter/setter。
- 创建 handler 对象,在
get中记录当前正在执行的副作用函数(即“依赖”) - 在
set中触发所有关联该属性的副作用函数重新执行 - 利用 WeakMap 存储每个响应式对象对应的依赖映射,避免内存泄漏
用 Object.defineProperty 精确控制单个属性
适用于已知结构的对象,兼容性更好(IE9+),但无法监听新增或删除属性,也不能代理数组索引变化。
- 遍历对象自有属性,对每个属性用
Object.defineProperty重定义 - 在 getter 中收集依赖(如将当前 activeEffect 加入 dep 集合)
- 在 setter 中判断值是否真正改变,若变化则遍历 dep 并执行所有 effect
实现依赖收集与触发的关键细节
观察者模式能否正确工作,取决于依赖是否精准捕获、是否及时清理、是否避免重复执行。
- 用栈管理嵌套 effect:执行 effect 前压入,结束后弹出,确保 get 时取到的是最内层的 activeEffect
- 每个属性对应一个 Dep(依赖集合),用 Set 存储 effect 函数,自动去重
- effect 执行前先从旧的 Dep 中清除自身,再在新的 get 过程中重新收集,防止残留依赖
结合 effect 与 reactive 构建响应式系统
把响应式逻辑封装成可复用的 API,让使用者专注业务,不关心底层拦截细节。
-
reactive(obj)返回一个被 Proxy 或 defineProperty 包装后的响应式代理 -
effect(fn)将 fn 包装为响应式副作用,自动追踪其内部读取的响应式属性 - 当响应式属性被修改,所有依赖它的 effect 自动重新运行,形成数据驱动视图的闭环











