Proxy需手动实现属性变更通知,核心是通过set等trap拦截操作并触发回调;支持多监听器管理、深层响应式代理及Reflect保证语义一致性。

Proxy 本身不自动通知属性变更,需要配合 Reflect 操作和自定义逻辑(比如触发回调、更新视图或发布事件)来实现“监听—响应”机制。核心在于拦截 set、deleteProperty 等关键 trap,并在其中主动执行通知逻辑。
用 set trap 拦截赋值并触发通知
这是最常用的方式:每当目标对象的属性被设置时,Proxy 的 set 方法会被调用。你可以在里面判断属性是否真的发生变化(避免无意义通知),然后调用预先注册的回调函数。
示例:
const handlers = {
set(target, key, value, receiver) {
const oldValue = target[key];
const result = Reflect.set(target, key, value, receiver);
if (oldValue !== value) {
console.log(`属性 ${key} 从 ${oldValue} 变更为 ${value}`);
// 这里可调用 updateView(key, value) 或 emit('change', key, value)
}
return result;
}
};
const obj = new Proxy({ count: 0 }, handlers);
obj.count = 5; // 输出:属性 count 从 0 变更为 5
支持多监听器与解耦设计
实际项目中,通常需要多个组件或模块响应同一属性变化。可以维护一个监听器列表(如 Map<key, Set<callback>>),并在 set 中批量触发:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
- 用
WeakMap关联代理对象与监听器集合,避免内存泄漏 - 提供
on(key, callback)和off(key, callback)方法管理订阅 - 在
set中检查该 key 是否有监听器,有则遍历执行
注意深层响应与数组变更
Proxy 默认只代理第一层属性。若属性值是对象或数组,其内部变化不会被拦截:
- 对嵌套对象,需递归代理(例如在
gettrap 中对返回的对象再 wrap 一层 Proxy) - 对数组方法(如
push、pop),要拦截set(索引赋值)、deleteProperty,以及重写原型方法或使用apply拦截方法调用 - 推荐用
Reflect.get+ 递归代理实现响应式数据结构,类似 Vue 3 的 reactive 原理
配合 Reflect 保证原语义正确
所有 trap 中应优先使用 Reflect.xxx 调用原操作,而不是直接操作 target —— 这能确保继承、getter/setter、不可写属性等行为与原生一致:
-
Reflect.set(target, key, value, receiver)正确处理 setter、proxy 链、this 绑定 - 直接写
target[key] = value会绕过 setter,且在严格模式下对不可写属性报错方式不同 - 返回
Reflect.set结果,保证 Proxy 行为与原对象一致

















