javascript中原型对象的constructor属性默认不可枚举。规范要求其enumerable为false,故for...in和object.keys()不可见;仅object.getownpropertynames()可枚举。常见误判源于手动重写prototype或显式设置enumerable为true。

JavaScript 中原型对象的 constructor 属性默认不可枚举,而不是可枚举。
这是一个常见误解。根据 ECMAScript 规范和主流引擎(V8、SpiderMonkey 等)的实际行为:
- 每个函数的
prototype对象在创建时,会自动获得一个constructor属性; - 这个属性是通过
Object.defineProperty的默认配置添加的,即:{ value: 构造函数, writable: true, enumerable: false, // ← 关键:默认为 false configurable: true } - 因此,
Person.prototype.constructor在for...in循环或Object.keys()中不会出现,因为它不可枚举。
为什么有人觉得它“可枚举”?
常见于以下两种情况:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
-
手动重写了整个
prototype:function Person() {} Person.prototype = { sayHi() { console.log('hi'); } }; // 此时 Person.prototype.constructor 指向 Object,且是可枚举的 // 因为字面量对象 `{}` 的所有自有属性默认 enumerable: true 显式用
Object.defineProperty设置了enumerable: true,或用Object.assign/展开运算符合并原型,导致constructor被覆盖为可枚举属性。
如何验证默认不可枚举?
function Person() {}
console.log(Person.prototype.propertyIsEnumerable('constructor')); // false
console.log(Object.keys(Person.prototype)); // [](空数组)
console.log(Object.getOwnPropertyNames(Person.prototype)); // ['constructor']
如果重写了 prototype,如何恢复正确状态?
Person.prototype = {
sayHi() { console.log('hi'); }
};
// 手动修复 constructor,并设为不可枚举
Object.defineProperty(Person.prototype, 'constructor', {
value: Person,
enumerable: false, // 必须显式设为 false
writable: true,
configurable: true
});
总结关键点:
-
默认的
constructor属性不可枚举,这是规范要求,保障for...in不意外遍历到它; - 可枚举现象几乎总是由重写原型对象或不规范赋值引入;
- 修复方式是用
Object.defineProperty显式控制enumerable: false。
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










