JavaScript对象字面量writable属性的默认配置机制完全解析
时间:2026-07-14 07:05
对象字面量中属性描述符默认全部开启,writable为true可直接赋值修改;而Object defineProperty定义的属性,writable、configurable、enumerable均默认为false,需手动设为true才能修改或枚举。两者默认行为差异显著。
对象字面量里的属性,默认情况下 `writable` 是 `true`,这意味着你可以直接通过赋值修改属性值。然而,许多开发者并不清楚,当使用 `Object.defineProperty` 定义属性时,默认行为正好相反——`writable` 默认是 `false`,必须手动设置为 `true` 才能允许修改。这种差异值得深入探讨。

用 `{ key: value }` 这种最自然的方式声明对象,JavaScript 会自动为每个属性生成三个描述符,并且全部默认开启:
- **writable: true** —— 允许通过 `obj.key = newValue` 直接修改属性值
- **enumerable: true** —— 属性会出现在 `for...in` 循环和 `Object.keys()` 的返回结果中
- **configurable: true** —— 允许删除该属性,或者使用 `Object.defineProperty` 重新配置描述符
对象字面量属性的 writable 行为
这种“全开”的默认行为与 `Object.defineProperty` 形成了鲜明对比。后者如果只传入 `value` 而不显式指定其他特性,那么 `writable`、`enumerable`、`configurable` 全部默认为 `false`。
- 字面量:`const obj = { x: 1 };` → `x` 是可写、可枚举、可配置的
- defineProperty:`Object.defineProperty(obj, 'y', { value: 2 });` → `y` 不可写、不可枚举、不可配置(除非手动设置为 true)
与 defineProperty 的关键区别
要验证某个属性的实际描述符状态,可以使用 `Object.getOwnPropertyDescriptor` 来一探究竟:
const obj = { a: 42 };
console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
// 输出:{ value: 42, writable: true, enumerable: true, configurable: true }
这里有一个容易忽略的点:你无法通过点号或方括号语法直接修改 `writable` 的值。想修改?必须再次调用 `Object.defineProperty`,而且前提是 `configurable` 仍然为 `true`。
验证 writable 状态的方法
一旦将 `writable` 设置为 `false`,赋值操作的效果取决于执行环境:
- 非严格模式下:`obj.a = 99` 会静默失败,`obj.a` 保持原值
- 严格模式下:`"use strict"; obj.a = 99` 会立即抛出 `TypeError`
设为 false 后的实际表现
最后提醒一点:这与 `const` 声明变量完全是两回事。`const obj = {...}` 锁定的是变量绑定,阻止你对 `obj` 重新赋值,但对象内部属性的可写性不受影响——该写还是能写,除非你主动将 `writable` 设置为 `false`。