Reflect 是 JavaScript 中标准化的底层属性操作封装,提供函数式接口以统一 Object、Proxy 和操作符的行为,核心价值在于提升可拦截性、可控性和安全性。
JavaScript 的 Reflect 对象不是用来实现动态类型或运行时类生成的“反射库”,而是把原本分散在 Object、Proxy 处理器方法、甚至操作符(如 in、delete)中的底层属性操作,统一成函数式接口。它的核心价值在于:让 Proxy 的 trap 方法签名和普通调用保持一致,同时提供更可控、可拦截、可组合的属性访问方式。
下面这些方法几乎覆盖日常属性读写场景,且每个都返回明确的布尔值或值,不抛异常(这点比直接操作更安全):
Reflect.get(target, key, receiver):替代 obj[key],支持自定义 receiver(影响 this 绑定,尤其对 getter 重要)Reflect.set(target, key, value, receiver):替代 obj[key] = value,返回 true/false 表示是否成功(严格模
式下失败会静默,而直接赋值会报错)Reflect.has(target, key):替代 key in target,可被 Proxy 拦截,语义更清晰Reflect.deleteProperty(target, key):替代 delete target[key],同样返回布尔值,避免意外静默失败Reflect.getOwnPropertyDescriptor(target, key):和 Object.getOwnPropertyDescriptor 行为一致,但属于 Reflect 命名空间,便于统一管理关键差异在失败处理与可拦截性:
obj.x = 1 在不可写属性上会抛 TypeError(非严格模式下静默失败),而 Reflect.set(obj, 'x', 1) 总是返回 false,不抛错,适合做防御性检查Reflect.set 支持第四个参数 receiver,当目标对象有 getter 且依赖 this 时,能精确控制上下文。例如:const obj = {
get x() { return this._v; }
};
const proxy = new Proxy(obj, {
set(target, key, value, receiver) {
// 这里 receiver 是 proxy,不是 target
return Reflect.set(target, key, value, receiver);
}
});Reflect 方法都可被 Proxy 完整拦截;而 Object.defineProperty 等静态方法无法被 Proxy 拦截 —— 它们作用于目标本身,绕过代理层这两个方法常被误认为只是 new Foo() 和 fn() 的函数化写法,但它们真正意义在于:支持动态构造器和显式指定 this,且与 Proxy 高度协同:
Reflect.construct(constructor, args, newTarget?):第三个参数 newTarget 可指定 new.target,用于继承链中正确触发子类 constructorReflect.apply(func, thisArg, args):比 func.apply(thisArg, args) 更轻量,不涉及 arguments 对象创建,也更容易被 Proxy 的 apply trap 拦截Reflect.get/set 等不处理原型链遍历逻辑 —— 它们只操作目标对象自身属性。要模拟 in 或 for...in,仍需配合 Object.prototype.hasOwnProperty 或 Object.keys
真正难的不是记住 API,而是判断何时该用 Reflect.set 而不是 Object.assign,或者为什么 Proxy handler 里必须用 Reflect 而不是直接操作目标 —— 这些边界往往出现在深拷贝、响应式系统或沙箱环境中。