enumerable 控制属性是否参与遍历操作,configurable 决定属性描述符能否被修改;前者影响 for...in、Object.keys 等可见性,后者限制 delete 和 defineProperty 的可变性。
识别 enumerable 和 configurable 对属性操作的限制,关键在于观察它们在不同场景下的“可见性”和“可变性”表现——不是看能不能读取值,而是看它在哪些操作中“露面”、哪些操作能“动它”。
通过枚举行为判断 enumerable 是否生效
enumerable 控制的是属性是否参与“遍历类操作”,跟能否访问值完全无关。你可以直接 obj.prop 拿到值,但它可能根本不会出现在以下场景中:
-
for...in循环:不可枚举属性不会被遍历(包括继承来的也不出现) -
Object.keys(obj):只返回对象自身的可枚举属性名 -
JSON.stringify(obj):忽略不可枚举属性,序列化结果里没有它 -
{...obj}扩展运算符 或Object.assign({}, obj):不可枚举属性不会被复制
验证方式很简单:
const obj = {};
Object.defineProperty(obj, 'hidden', {
value: 'secret',
enumerable: false,
configurable: true
});
console.log(Object.keys(obj)); // []
console.log('hidden' in obj); // true(仍可访问)
console.log(obj.hidden); // 'secret'
通过删除与重定义行为判断 configurable 是否受限
configurable 决定的是“这个属性本身还能不能被改动”。一旦设为 false,就锁死了它的元信息——不只是删不掉,连描述符配置都冻结了:
-
delete obj.prop:静默失败(非严格模式)或报TypeError(严格模式) -
Object.defineProperty(obj, 'prop', {...}):若尝试修改value、writable、enumerable、configurable中任意一项,会报错 - 唯一允许的例外:
writable: true → false可以改;但false → true不行(即使 configurable 是 true)
典型测试代码:
const obj = {};
Object.defineProperty(obj, 'locked', {
value: 42,
writable: false,
enumerable: false,
configurable: false
});
delete obj.locked; // 无效果(非严格)或报错(严格)
// 下面这行在任何模式下都会报错:
// Object.defineProperty(obj, 'locked', { enumerable: true });
用 getOwnPropertyDescriptor 快速查看当前描述符状态
最直接的办法是调用 Object.getOwnPropertyDescriptor(obj, 'prop'),它返回完整的描述符对象,包含 value、writable、enumerable、configurable 四项(数据描述符)或 get/set(存取描述符):
- 如果返回
undefined,说明该属性不存在,或它是原型链上的不可枚举属性(需用Object.getPrototypeOf()追溯) - 如果返回对象,直接看
enumerable和configurable的布尔值即可确认当前限制
例如:
const obj = { a: 1 };
Object.defineProperty(obj, 'b', { value: 2, enumerable: false });
console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
// { value: 1, writable: true, enumerable: true, configurable: true }
console.log(Object.getOwnPropertyDescriptor(obj, 'b'));
// { value: 2, writable: false, enumerable: false, configurable: true }
注意默认值差异带来的误判风险
不同创建方式导致初始描述符不同,容易让人误以为“限制是代码加的”,其实是默认行为:
- 对象字面量
{ x: 1 }创建的属性:默认enumerable: true、configurable: true、writable: true - 用
Object.defineProperty()显式添加:所有布尔描述符默认为false(除非你明确写true)
所以看到一个属性“删不掉”或“for...in 看不见”,先检查是不是 defineProperty 时漏写了 enumerable: true 或 configurable: true,而不是怀疑语法出错。

















