Object.defineProperty() 中属性描述符有严格默认值:数据属性的 writable、enumerable、configurable 默认均为 false,value 为 undefined;访问器属性的 get/set 未设置时为 undefined,enumerable 和 configurable 同样默认 false;而字面量属性三者默认均为 true。

在 JavaScript 中,使用 Object.defineProperty() 或 Object.defineProperties() 定义属性时,属性描述符(property descriptor)的各个字段有明确的默认值规则。这些默认值会影响属性的行为,比如是否可写、是否可枚举、是否可配置,稍不注意就容易引发意外行为。
数据属性描述符的默认值
当传入一个“空”描述符对象(如 {})时,JavaScript 并不会直接报错,而是按规则补全缺失字段。对数据属性(即含 value 或 writable 的描述符),默认值如下:
-
value:未显式设置时为
undefined -
writable:默认为
false(注意:不是true!) -
enumerable:默认为
false -
configurable:默认为
false
这意味着,哪怕只写 Object.defineProperty(obj, 'x', {}),得到的也是一个不可写、不可枚举、不可删除/重定义的属性——相当于“冻结”的初始状态。
访问器属性描述符的默认值
若描述符中包含 get 或 set(即访问器属性),则 value 和 writable 会被忽略,此时默认规则不同:
立即学习“Java免费学习笔记(深入)”;
-
get 和 set:未设置时均为
undefined(但至少一个必须存在,否则抛错) -
enumerable:仍默认为
false -
configurable:仍默认为
false
例如:Object.defineProperty(obj, 'y', { get() { return 42; } }) 创建的属性是不可枚举、不可配置的,且没有 set,即只读访问器。
与字面量属性声明的差异
直接用对象字面量定义的属性(如 const obj = { a: 1 })行为不同:它们的 writable、enumerable、configurable 全部默认为 true。这种“友好默认”仅适用于字面量初始化,不适用于 defineProperty。混用时容易误判——比如把字面量属性再用 defineProperty “覆盖”,却忘了显式设 writable: true,结果属性突然变只读。
如何安全地复用描述符或批量定义
为避免默认值陷阱,建议显式声明关键字段,尤其在封装工具函数时:
- 需要可写的属性,务必写
writable: true - 希望被
for...in或Object.keys()遍历,加enumerable: true - 预留后续修改空间(如后期要删或改描述符),设
configurable: true - 可借助
Object.getOwnPropertyDescriptor()查看已有属性的实际描述符,验证是否符合预期
不复杂但容易忽略。


















