Proxy需按需代理嵌套对象:在get中对对象类型值递归代理,用WeakMap缓存防重复;set中同样代理新值;ownKeys、has等操作需手动实现以保证枚举一致性。

Proxy 默认只代理对象的第一层属性,要让嵌套对象(比如 obj.user.profile.name)也具备拦截能力,必须在 get 拦截器中对返回值做“按需代理”——即每次访问到一个对象类型的属性时,动态创建并返回它的代理版本,而不是直接暴露原始对象。
核心:在 get 中实现懒代理
每次从目标对象读取属性后,检查其值是否为对象(且非 null),是则递归包装成新 Proxy;否则原样返回。这样既避免初始化时全量递归的性能开销,又保证深层访问仍能触发拦截逻辑。
- 用
typeof value === 'object' && value !== null判断是否可代理 - 跳过
Date、RegExp、Map、Set等内置对象,防止行为异常 - 对数组也要代理,否则
arr.push()返回的新数组会脱离监听
防重复代理与循环引用
同一原始对象可能被多次访问(如 obj.a.b 和 obj.c.d 指向同一个对象),若每次都新建 Proxy,会导致内存泄漏或无限递归。WeakMap 是天然解法:
- 以原始对象为 key,代理对象为 value 存入 WeakMap
- 每次
get前先查缓存,命中则直接返回已有代理 - WeakMap 的弱引用特性可避免内存泄漏,尤其适合长期存活的对象树
set 和 deleteProperty 要同步处理新值
赋值操作不只是写入,还可能引入新的嵌套结构。例如 obj.user = { info: { age: 30 } },这个新对象也需要被代理,否则后续修改 obj.user.info.age 就不会触发响应。
立即学习“Java免费学习笔记(深入)”;
- 在
set拦截器中,对即将设入的value同样执行一次代理逻辑(查缓存 → 懒创建) -
deleteProperty需配合通知机制(如触发更新回调),确保视图能感知删除动作 - 注意:不能直接在
set里调用Reflect.set后就返回,要确保新值已就绪
补充细节:ownKeys、has、in 等操作需显式支持
Proxy 不会自动拦截 Object.keys()、for...in 或 prop in obj 这类枚举行为。如果需要完整语义,得手动实现 ownKeys 和 has:
-
ownKeys应返回目标对象自身的可枚举属性键(可用Reflect.ownKeys(target)) -
has可复用Reflect.has(target, prop),保持与原生一致 - 若对象有 Symbol 属性或不可枚举字段,需额外处理,否则代理后行为不一致


















