Reflect.set 设置对象属性为什么没有生效?

迷人的诗雅 阅读 16

我在用 Reflect.set 动态修改对象属性时遇到了奇怪的问题。比如定义了一个不可变属性:


const obj = {};
Object.defineProperty(obj, 'test', {
  value: 1,
  writable: false,
  enumerable: true,
  configurable: false
});

然后尝试用 Reflect.set(obj, 'test', 2) 修改值,但控制台报错 TypeError: Cannot assign to read only property 'test'...。可是如果直接写 obj.test = 2 却不会报错,只是值没变。这两种方式不是应该表现一致吗?我应该怎样正确用Reflect修改不可变属性呢?

我来解答 赞 2 收藏
二维码
手机扫码查看
2 条解答
艳鑫🍀
这个问题其实挺有意思的,Reflect.set 和直接赋值在处理不可变属性时确实表现不太一样。咱们先说结论:你遇到的这个情况是因为 Reflect.set 在尝试修改一个不可变属性时,如果修改失败,它会抛出 TypeError,而直接赋值 obj.test = 2 不会抛错,只是默默地不生效。

原因在于 Reflect.set 的设计初衷就是要更严格地反映属性设置的真实结果。当一个属性被定义为 writable: false 时,直接赋值会被 JavaScript 引擎忽略,但不会报错;而 Reflect.set 则会明确告诉你这事儿没成,通过抛出异常的方式。

如果你真的需要修改这个属性,那得确保它是 configurable: true,因为只有这样你才能通过 Object.defineProperty 或者 Reflect.defineProperty 来重新定义这个属性。比如:

const obj = {};
Object.defineProperty(obj, 'test', {
value: 1,
writable: false,
enumerable: true,
configurable: true // 注意这里改成了 true
});

// 先删除原来的属性
Reflect.deleteProperty(obj, 'test');

// 然后重新定义
Reflect.defineProperty(obj, 'test', {
value: 2,
writable: true,
enumerable: true,
configurable: false
});

console.log(obj.test); // 输出 2


不过说实话,这种操作一般只在特殊场景下才用得上,比如写一些框架或者工具库的时候。平常开发中,建议尽量避免去折腾不可变属性,省得给自己找麻烦。

希望能帮到你!如果还有其他问题随时问。
点赞
2026-02-19 19:03
慧玲 ☘︎
Reflect.set 的行为其实是符合规范的,它会严格遵循属性描述符的定义。你设置了 writable: false,说明这个属性不可写,Reflect.set 在这种情况下会返回 false 或者在严格模式下抛出错误,这取决于调用上下文。

而 obj.test = 2 不报错是因为在非严格模式下,对不可写属性赋值只是静默失败,不会抛异常,但实际值也不会改变。如果你在严格模式下写 obj.test = 2,一样会报 TypeError。

所以两者行为其实是一致的:都不能修改不可写属性。区别只在于是否抛错,这由执行模式决定。

如果你想通过 Reflect.set 成功修改属性,必须确保属性是可写的。可以这样重新定义:

const obj = {};
Object.defineProperty(obj, 'test', {
value: 1,
writable: true, // 改成可写
enumerable: true,
configurable: false
});

Reflect.set(obj, 'test', 2); // 这时候就能成功
console.log(obj.test); // 输出 2


或者一开始用普通赋值方式定义属性,默认就是可写的:

const obj = { test: 1 }; // writable 默认 true
Reflect.set(obj, 'test', 2); // 正常工作


总结:Reflect.set 不是“更强”的赋值方式,它只是更严格地遵守对象属性的元数据定义。要修改属性,先保证它是 writable: true。试试这个方法应该就没问题了。
点赞 4
2026-02-09 18:27