Proxy 是 JavaScript 中实现对象属性动态拦截与修改的最标准灵活方式,通过 handler 的 get/set 等 trap 拦截操作,结合 Reflect 转发默认行为,并支持递归代理嵌套对象及处理数组等细节。

JavaScript 中通过 Proxy 实现对象属性的动态拦截与修改,这是最标准、最灵活的方式。它不修改原对象,而是创建一个代理层,在访问或设置属性时插入自定义逻辑。
用 Proxy 拦截 get/set 操作
Proxy 构造函数接收目标对象和处理器(handler)对象,handler 中定义 trap(陷阱)方法,如 get 和 set,用于拦截读取和赋值行为。
-
get(target, prop, receiver):拦截属性读取,可返回计算值、触发副作用、做权限检查等 -
set(target, prop, value, receiver):拦截属性赋值,可验证、转换、拒绝或同步更新其他状态 - 注意
receiver参数(通常是 proxy 本身),在处理原型链或 setter 中的this时很重要
支持深层响应式与嵌套拦截
Proxy 默认只拦截第一层,要实现嵌套对象的自动代理,需在 get 中对返回的值做判断:若为对象,递归包装成新 Proxy。
- 避免无限递归:可用 WeakMap 缓存已代理对象,查表复用
- 数组操作也需单独处理(如
push、length变更),可通过ownKeys、defineProperty等 trap 补充 - 常见框架(如 Vue 3)正是基于此思路构建响应式系统
配合 Reflect 实现默认行为转发
在 trap 中不应直接操作 target,而应调用 Reflect 对应方法(如 Reflect.get()、Reflect.set())来执行原生逻辑,保证语义一致性和可预测性。
立即学习“Java免费学习笔记(深入)”;
- Reflect 方法签名与 trap 完全匹配,天然适配
- 例如:
return Reflect.get(target, prop, receiver)是安全的默认读取 - 错误处理更清晰:Reflect 方法返回布尔值(如
Reflect.set返回是否成功),便于控制流程
实际应用中的关键细节
Proxy 不是万能的,使用时需注意边界情况和性能影响。
- 无法拦截私有字段(
#field),仅对常规属性有效 - in 操作符、
for...in、Object.keys()等由ownKeys和has控制,需显式实现 - Proxy 对象与原对象不相等(
proxy !== target),且无法被instanceof或Array.isArray()正确识别,必要时用getPrototypeOf或isExtensible补齐


















