ES6 class 的 getter/setter 仅是语法糖,不自动响应变化;需手动实现依赖收集与触发更新,但无法监听深层属性或数组索引,推荐用 Proxy 替代。

ES6 的 class 本身不提供响应式能力,getter/setter 只是语法糖,用于拦截属性读写,但**不会自动触发更新或监听变化**。要实现“响应式”,需配合手动依赖收集、触发更新等机制(类似 Vue 2 的核心思路)。下面讲清楚怎么用 getter/setter 搭建一个极简响应式模型。
用 getter/setter 封装内部状态
避免直接暴露原始属性,把数据存在私有字段(如 _value),再通过 getter/setter 控制访问:
class Reactive {
constructor(value) {
this._value = value;
}
get value() {
console.log('读取 value');
return this._value;
}
set value(newValue) {
console.log('设置 value 为', newValue);
this._value = newValue;
}
}
这样每次读写 obj.value 都会进入自定义逻辑,为响应式埋下钩子。
手动添加依赖收集与触发更新
响应式的本质是:读取时“记下谁在用我”(收集依赖),修改时“通知所有依赖更新”(触发更新)。可借助一个全局的依赖栈和回调队列:
立即学习“Java免费学习笔记(深入)”;
- 用
let activeEffect = null记录当前正在执行的副作用函数 - 每个响应式属性维护一个
deps数组,存所有依赖它的函数 - getter 中把
activeEffect加入deps - setter 中遍历
deps并执行每个函数
let activeEffect = null;
class Reactive {
constructor(value) {
this._value = value;
this.deps = new Set();
}
get value() {
if (activeEffect) {
this.deps.add(activeEffect);
}
return this._value;
}
set value(newValue) {
this._value = newValue;
this.deps.forEach(fn => fn());
}
}
// 使用示例
const obj = new Reactive(1);
function effect(fn) {
activeEffect = fn;
fn(); // 初次执行,触发 getter 收集依赖
activeEffect = null;
}
effect(() => {
console.log('视图更新:', obj.value); // 读取时收集
});
obj.value = 2; // 触发所有依赖执行 → 打印新值
支持嵌套对象与数组(简化版)
原生 getter/setter 无法监听对象深层属性或数组索引赋值。需要递归代理或重写关键方法:
- 对对象属性,用
Object.keys()遍历,为每个属性创建响应式包装 - 对数组,重写
push、pop、splice等会改变长度的方法,在内部手动触发更新 - 更稳妥的做法是用
Proxy替代 class + getter/setter(ES6+ 推荐方案)
注意:仅靠 class 内部的 getter/setter 无法自动代理子属性,必须显式包装或使用 Proxy。
为什么不直接用 Proxy?
Proxy 能监听任意属性(包括动态新增、数组索引、in 操作符等),而 class 的 getter/setter 必须提前声明每个属性名。Vue 3 已全面切换到 Proxy 实现响应式。若坚持用 class,建议只用于封装单个基础值(如计数器、开关),复杂状态推荐:
- 用
Proxy包裹 plain object - 或使用成熟库如
solid-js、valtio的响应式 store - 避免重复造轮子,尤其在生产环境


















