javascript中通过object.defineproperty()或defineproperties()可精确控制属性的writable和enumerable等描述符;writable为false时属性不可赋值,enumerable为false时不参与遍历;未显式指定的描述符默认为false,易导致属性被意外锁定。

JavaScript 中通过 Object.defineProperty() 或 Object.defineProperties() 设置属性描述符(property descriptor),可以精确控制属性是否可枚举(enumerable)、是否可写(writable)、是否可配置(configurable)等行为。
用 defineProperty 控制单个属性的可枚举与可写性
调用 Object.defineProperty(obj, prop, descriptor) 时,传入的 descriptor 对象可包含 writable 和 enumerable 字段:
-
writable: false→ 属性值不可被重新赋值(严格模式下赋值会报错,非严格模式静默失败) -
enumerable: false→ 该属性不会出现在for...in循环、Object.keys()、JSON.stringify()等枚举操作中
示例:
const obj = {};
Object.defineProperty(obj, 'name', {
value: 'Alice',
writable: false,
enumerable: true,
configurable: false
});
Object.defineProperty(obj, 'age', {
value: 25,
writable: true,
enumerable: false, // 不会被遍历到
configurable: true
});
console.log(obj.name); // 'Alice'
obj.name = 'Bob'; // 无效(writable: false)
console.log(obj.age); // 25
console.log(Object.keys(obj)); // ['name'] —— age 不出现(enumerable: false)
批量定义多个属性:defineProperties
当需要同时设置多个属性的描述符时,用 Object.defineProperties() 更简洁:
const person = {};
Object.defineProperties(person, {
firstName: {
value: 'John',
writable: false,
enumerable: true
},
lastName: {
value: 'Doe',
writable: true,
enumerable: false
}
});
console.log(person.firstName); // 'John'
for (let key in person) {
console.log(key); // 只输出 'firstName'
}
检查现有属性的描述符
用 Object.getOwnPropertyDescriptor(obj, prop) 查看当前属性的完整描述符:
const obj = { x: 1 };
Object.defineProperty(obj, 'y', { value: 2, writable: false, enumerable: false });
console.log(Object.getOwnPropertyDescriptor(obj, 'x'));
// { value: 1, writable: true, enumerable: true, configurable: true }
console.log(Object.getOwnPropertyDescriptor(obj, 'y'));
// { value: 2, writable: false, enumerable: false, configurable: false }
注意 writable 和 enumerable 的默认值
使用字面量对象直接定义的属性,默认描述符为:
writable: trueenumerable: trueconfigurable: true
但通过 defineProperty 显式定义时,未指定的字段默认为 false(不是继承自对象原型,而是描述符本身的默认值)——这点容易忽略:
Object.defineProperty(obj, 'z', { value: 42 });
// 等价于:
// { value: 42, writable: false, enumerable: false, configurable: false }
所以务必显式声明你需要的行为,否则可能意外锁定属性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











