Reflect.set 仅在目标对象自身设置属性,不查找原型链、不触发上游setter;它等价于obj.prop = value的规范化接口,返回布尔值表示成败,并通过receiver参数控制setter中的this指向。

Reflect.set 不是“智能赋值”工具,它不查找原型链、不自动代理、也不触发上游 setter —— 它只做一件事:在目标对象自身上设置属性,并严格按 ECMAScript 规范执行赋值语义。
它本质上是 = 操作符的规范化底层接口
当你写 obj.x = 123,引擎内部会调用类似 [[Set]] 的抽象操作;Reflect.set(obj, 'x', 123) 就是把这个操作暴露为可编程的函数形式。关键区别在于:
- 返回布尔值(
true表示成功,false表示失败),而非抛异常(严格模式下普通赋值会报错,它不会) - 始终只作用于
target对象自身,完全忽略原型链上的同名属性(哪怕父级有可写的x,它也不会去碰) - 若目标对象不可扩展(
Object.preventExtensions()),或属性已存在且writable: false,则返回false
第四个参数 receiver 决定 setter 中的 this
当目标属性是一个 setter(即定义了 set 描述符),Reflect.set 会把 receiver 作为该 setter 执行时的 this 值。这在 Proxy 场景中尤其关键:
- 省略
receiver时,默认为target - 显式传入时,例如
Reflect.set(obj, 'x', val, proxy),即使obj上有 setter,其内部this也会指向proxy,而非obj - 这是 Proxy 的
settrap 能正确转发并维持原始接收者语义的基础
它不处理原型链,但可以被组合用于链式赋值逻辑
Reflect.set 自身不遍历原型,但它提供了可靠、可判断的返回值,便于你构建更复杂的赋值策略:
- 想“写入第一个可写的同名原型属性”?需手动用
Object.getPrototypeOf()向上查找,再对匹配对象调用Reflect.set - 想“仅当自身无该属性时才写入原型”?先用
Object.prototype.hasOwnProperty.call(target, key)判断,再决定是否操作原型 - 它和
Reflect.getOwnPropertyDescriptor、Reflect.getPrototypeOf配合,能精确控制赋值位置与权限
它和 Proxy 的 set trap 是默认映射关系
Proxy 的 set(target, prop, value, receiver) trap 若未显式实现,其默认行为就是调用:
Reflect.set(target, prop, value, receiver)
这意味着:
- 所有 Proxy 的 set 操作,底层都依赖
Reflect.set的语义 - 如果你重写了
settrap,又希望保留原语义,直接return Reflect.set(...)是最安全做法 - 这也解释了为什么 Vue3 响应式系统基于 Proxy + Reflect:它们共同封装了可拦截、可定制、可预测的属性赋值过程

















