object.defineproperty设属性为只读需确保configurable为true,否则无法修改writable;默认普通对象属性configurable:true,可先用getownpropertydescriptor检查;设writable:false后赋值在严格模式报错、非严格模式静默失败;模拟常量建议同时设configurable:false和enumerable:false。

直接用 Object.defineProperty 把已有属性设为只读(writable: false)是可行的,但要注意:该操作仅在属性本身是“可配置”的前提下才真正生效;一旦属性已被设为 configurable: false,后续就无法再修改其 writable 状态——这是关键限制。
确保目标属性可配置
JavaScript 中普通对象属性默认是 configurable: true、writable: true、enumerable: true。只有保持 configurable: true,才能后续调用 defineProperty 关闭写权限:
- 如果属性是通过字面量或
Object.assign添加的,通常满足条件 - 若之前已执行过
Object.defineProperty(obj, key, { configurable: false }),则不能再升级为只读 - 可先检查:
Object.getOwnPropertyDescriptor(obj, 'key')确认configurable为true
执行只读升级操作
调用 Object.defineProperty 时只需传入 writable: false,其他描述符可省略(会保留原值):
const obj = { PI: 3.14159 };
// 升级为只读
Object.defineProperty(obj, 'PI', { writable: false });
obj.PI = 3.14; // 非严格模式下静默失败;严格模式抛 TypeError
console.log(obj.PI); // 仍输出 3.14159
增强鲁棒性:同时锁定配置与枚举
若目标是模拟“系统常数”(如 Math.PI),建议一并设为不可配置、不可枚举:
-
configurable: false:防止被删除或再次修改描述符 -
enumerable: false:避免出现在for...in或Object.keys()中 - 这样更接近内置常量的行为,且只需设置一次
示例:
Object.defineProperty(obj, 'VERSION', {
value: '2.0.0',
writable: false,
enumerable: false,
configurable: false
});
注意边界情况
以下情形会导致升级失败或行为异常:
- 对
let/const声明的变量名使用defineProperty无效(它们绑定在词法环境,不挂载于全局对象) - 在严格模式下给只读属性赋值会立即报错;非严格模式下赋值被忽略,无提示
- 数组长度(
length)、函数name等原生属性可能有特殊保护,不能随意重定义
不复杂但容易忽略的是:可配置性必须前置保留。把普通属性变成可靠常数,核心不在“写不写得进去”,而在“能不能锁得住”。











