Proxy用于拦截并自定义对象操作,Reflect提供与之对应的静态方法使底层操作显式化、标准化;二者协同实现权限控制、响应式系统、日志记录等元编程能力。

JavaScript 代理(Proxy)与反射(Reflect)是一对协同工作的底层机制,Proxy 用于拦截并自定义对象的基本操作,Reflect 则提供了一组与 Proxy 拦截器一一对应的静态方法,让原本隐式执行的操作显式化、标准化。
代理(Proxy):控制对象行为的“中间层”
Proxy 允许你创建一个包装对象(proxy),在访问目标对象(target)时插入自定义逻辑。它通过 handler 对象定义各种“陷阱”(traps),比如 get、set、has、deleteProperty、apply 等。只要对 proxy 执行对应操作,就会触发 handler 中的相应方法。
- 可实现属性访问权限控制:例如只读视图、字段过滤、懒加载
- 能自动验证赋值:在 set 中检查类型、范围或格式,抛出错误或转换值
- 支持透明的响应式系统:Vue 3 的 reactive 就基于 Proxy 实现依赖追踪
- 可记录操作日志、统计调用次数、模拟远程对象(如 RPC 代理)
反射(Reflect):让对象操作变得可编程
Reflect 不是构造函数,而是一个只读的内置对象,包含 13 个与 Proxy trap 同名的静态方法(如 Reflect.get、Reflect.set)。它的设计初衷是把过去分散在 Object、Function 或操作符中的底层行为统一收口,并返回布尔结果(成功 true,失败 false),避免异常中断流程。
- 替代部分 Object 方法:Reflect.has(obj, key) 比 key in obj 更可靠(不触发原型链上的 getter)
- 配合 Proxy 使用更自然:handler.set = (target, key, val) => Reflect.set(target, key, val * 2)
- 支持动态方法调用:Reflect.apply(fn, thisArg, args) 替代 fn.apply(thisArg, args),更安全可控
- 便于条件性操作:Reflect.defineProperty 可返回布尔值,方便判断是否设置成功
组合使用:构建可扩展的对象抽象
Proxy + Reflect 是现代 JS 元编程的核心组合。它们让开发者能在不修改原始对象的前提下,叠加校验、日志、缓存、序列化、沙箱隔离等能力。
立即学习“Java免费学习笔记(深入)”;
- 创建带默认值的对象:get trap 中用 Reflect.get 回退到默认值
- 实现不可变代理:set/deleteProperty trap 直接返回 false 或 throw 错误
- 构建调试代理:所有操作前打印参数,后打印结果,不影响原逻辑
- 实现私有字段模拟:约定 _ 开头为私有,在 has/get/set 中拦截并拒绝外部访问
注意事项与限制
Proxy 无法代理普通变量、基本类型(需包装成 Object)、某些内置对象(如 Date、Promise 构造器)的部分行为;且一旦代理创建,无法撤销(ES2022 新增 WeakRef 和 FinalizationRegistry 可辅助管理,但无原生 revoke)。Reflect 方法不能被单独 polyfill,必须依赖引擎支持。
不复杂但容易忽略:Proxy handler 中若未定义某个 trap,对应操作会直接转发给目标对象;而 Reflect 方法调用失败通常返回 false 而非抛错,需主动判断。











