Reflect API 是将隐式操作显式化、可拦截化的工具,不提供新能力但使 Proxy 拦截更完整;其方法如 Reflect.set()、Reflect.has()、Reflect.construct() 等专为 Proxy 场景设计,确保拦截生效、行为可控且无副作用。

Reflect API 不是“更好”的替代品,而是把原本散落在 Object、prototype、运算符里的隐式行为显式化、可拦截化。它本身不提供新能力,但让 Proxy 拦截更完整、代码意图更清晰。
为什么 Reflect.set() 比 obj[key] = value 更适合 Proxy 场景
直接赋值会跳过 Proxy 的 set 拦截器,而 Reflect.set() 是唯一能确保触发该拦截的规范方式。
- 在 Proxy handler 里必须用
Reflect.set(target, key, value, receiver),否则递归调用会绕过拦截 -
receiver参数控制this绑定,比如处理 setter 或原型链继承时必不可少 - 返回布尔值(成功/失败),比抛异常更易做条件判断;而
obj.x = y总是返回y,失败时才抛错
Reflect.has() 和 in 运算符的区别在哪
in 查属性存在性时会查原型链,但无法被 Proxy 拦截;Reflect.has() 是唯一能被 has 拦截器捕获的等价操作。
- Proxy handler 中写
has(target, key) { return key in target; }是错误的——这又触发了原始in,造成无限递归 - 正确写法是:
has(target, key) { return Reflect.has(target, key); } -
Reflect.has()行为严格对应in,但它是函数调用,可被拦截、可传参、可封装
哪些操作只有 Reflect 能做,Object 无法替代
不是所有 Reflect 方法都有 Object 对应物。有些操作原本就没有顶层 API,只能靠 Reflect 暴露出来。
立即学习“Java免费学习笔记(深入)”;
-
Reflect.construct():模拟new Foo(...args),支持指定new.target和自定义 prototype,Object完全没有对应方法 -
Reflect.apply():安全调用函数并控制this和参数数组,比fn.apply(thisArg, args)更底层,且能被 Proxy 的apply拦截 -
Reflect.getOwnPropertyDescriptor():和Object.getOwnPropertyDescriptor()行为一致,但它是 Reflect 命名空间下统一风格的一部分,便于和其它 Reflect 方法组合使用
const handler = {
apply(target, thisArg, args) {
console.log('函数被调用,参数:', args);
// 必须用 Reflect.apply 才能真正执行原函数并保持 this 和 new.target 正确
return Reflect.apply(target, thisArg, args);
}
};
const fn = () => 'hello';
const proxied = new Proxy(fn, handler);
proxied(1, 2); // 输出日志,并返回 'hello'
最容易被忽略的是:Reflect 方法全部是“不可配置、不可枚举、不可写”的静态函数,它们不依赖 this,也不修改目标对象——这意味着你在 Proxy handler 里调用它们时,完全不用担心 this 绑定或副作用。但反过来,这也意味着你不能靠 monkey patch Reflect.set 来全局劫持赋值,它只是规范定义的一组纯操作入口。











