深度代理通过get拦截对嵌套对象“懒代理”实现:访问时递归用Proxy包裹对象,WeakMap缓存防重复;set时对新对象值再代理;需透出Date/RegExp等内置对象,避免代理全局对象。

Proxy 本身只代理一层,要实现深度代理嵌套,核心思路是:在 get 拦截中对返回的属性值做“懒代理”——只有访问到嵌套对象时,才递归用 Proxy 包裹它。
递归代理:每次 get 返回新 Proxy
关键在于不让原始嵌套对象暴露出去。只要某个属性值是对象(包括数组、函数等),就用同样的 handler 再包一层。
- 判断返回值是否为对象且非 null,再用
new Proxy(value, handler)包装 - 避免重复代理:可加缓存(WeakMap)记录已代理过的对象,防止无限循环或内存泄漏
- 注意数组方法(如
push、map)返回的新数组也要被代理,否则链式调用会断层
处理 set 和 delete:保持响应式语义
set 拦截不仅要赋值,还要对新值做代理;deleteProperty 需触发依赖更新(如果用于响应式系统)。
- 赋值时若新值是对象,先代理再设入目标
- 删除属性后应通知监听者(如 Vue 的
trigger或自定义事件) - 对
in操作符、Object.keys()等需重写ownKeys和has
避开陷阱:null、Date、RegExp、内置构造器
不是所有对象都适合代理。原始类型(string/number/boolean)直接返回;Date、RegExp、Promise 等内置对象代理后行为异常,应原样透出。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 用
Object.prototype.toString.call(val)精准判断类型 - 对
val instanceof Date或val instanceof RegExp直接返回原值 - 避免代理 window、document 等全局对象(会报错或引发安全限制)
简易可运行示例
下面是一个最小可用的深度代理工厂:
function deepProxy(obj, handler = {}) {
const proxied = new WeakMap();
const baseHandler = {
get(target, key, receiver) {
const val = Reflect.get(target, key, receiver);
if (val !== null && typeof val === 'object') {
if (!proxied.has(val)) {
proxied.set(val, new Proxy(val, baseHandler));
}
return proxied.get(val);
}
return val;
},
set(target, key, value, receiver) {
if (value !== null && typeof value === 'object') {
value = deepProxy(value);
}
return Reflect.set(target, key, value, receiver);
},
...handler
};
return new Proxy(obj, baseHandler);
}
调用 deepProxy({ a: { b: { c: 1 } } }) 后,proxy.a.b.c 修改会触发对应层级的 set,且 proxy.a.b 本身也是代理对象。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










