近日发现:为什么即使设置 writable:false ,你的属性依然被修改?是引擎出轨了还是代码缩水了?让我今天来聊一聊 get 和 set 的小细节。
在 JavaScript 中,访问描述符(Accessor Descriptor) 和 数据描述符(Data Descriptor) 是两种不同的属性描述符类型,又要找不同了吗:

1. 数据描述符(value
+ writable
)
-
适用于普通属性,如:
jsconst obj = {}; Object.defineProperty(obj, 'name', { value: 'Alice', writable: false, // 控制是否可修改 }); obj.name = 'Bob'; // 静默失败(严格模式会报错) console.log(obj.name); // 'Alice'(未被修改)
- 如果
writable: false
,则value
不可被重新赋值 (无论是直接赋值还是Object.defineProperty
修改)。
- 如果
2. 访问描述符(get
+ set
)
-
适用于 计算属性 (通过 getter/setter 动态控制):
jsconst obj = {}; Object.defineProperty(obj, 'name', { get() { return this._name; }, set(val) { this._name = val; }, // 注意:这里没有 `value` 或 `writable`! }); obj.name = 'Bob'; // 调用 setter console.log(obj.name); // 'Bob'(通过 getter 获取)
-
访问描述符会忽略
value
和writable
,只关心get
和set
。 -
即使你强行加上
writable: false
,只要提供了set
,属性依然可写 :jsObject.defineProperty(obj, 'name', { get() { return this._name; }, set(val) { this._name = val; }, writable: false, // 被忽略! }); obj.name = 'Bob'; // 仍然可以调用 setter
-
加false都能写,我直接狠狠地
了。
3. 冲突规则
-
如果同时提供
value
/writable
和get
/set
,JS 会报错:js// 错误示例! Object.defineProperty(obj, 'name', { value: 'Alice', get() { return 'Bob'; }, // TypeError: Invalid property descriptor });
总结
描述符类型 | 关键属性 | writable: false 的影响 |
---|---|---|
数据描述符 | value , writable |
阻止直接修改 value |
访问描述符 | get , set |
writable 被忽略 ,由 set 控制 |
其实文章看总结感觉就够了,加深理解再去看例子。

结论:
-
对于 访问描述符 ,
writable
无意义,是否可写完全由set
是否存在决定。 -
如果你希望一个访问器属性 只读 ,直接 不提供
set
即可:jsObject.defineProperty(obj, 'readOnlyProp', { get() { return 'Cannot change me!'; }, // 无 setter }); obj.readOnlyProp = 'New'; // 静默失败(严格模式报错)
谢谢观看
