JavaScript constructor隐式调用与显式定义
作者:技术拾光时间:2026-07-07 08:49:12浏览:139
先拆解一个问题:JavaScript 中 constructor 这个属性,到底是如何工作的?很多人误以为它会被“隐式调用”,但实际上,constructor 本身不会被自动调用——它只是原型对象上的一个属性,指向对应的构造函数。真正被隐式关联或自动设置的,是 prototype 与 __proto
先拆解一个问题:JavaScript 中 constructor 这个属性,到底是如何工作的?很多人误以为它会被“隐式调用”,但实际上,constructor 本身不会被自动调用——它只是原型对象上的一个属性,指向对应的构造函数。真正被隐式关联或自动设置的,是 prototype 与 __proto__ 的关系,而 constructor 不过是这个关系里“附带存在”的一个引用。

constructor 是什么?它从哪来?
constructor 是每个函数的 prototype 对象上默认自带的属性,值指向该函数自身。它不是语言运行时“调用”的东西,而是一个指针,用来标识“谁造出了我”。
- 定义函数时,引擎会自动为它的
prototype添加constructor: 指向该函数。 - 举个例子:
function Person() {}之后,Person.prototype.constructor === Person(结果为true)。 - 实例对象本身没有
constructor属性,但可以通过原型链访问到:new Person().__proto__.constructor === Person。
显式定义 constructor 的常见场景
当手动重写函数的 prototype 时,constructor 会丢失,必须显式恢复,否则会破坏原型链的可追溯性。
- 错误写法:
Person.prototype = { say() { } };—— 此时Person.prototype.constructor指向Object,不再是Person。 - 正确补救:
Person.prototype = { say() {}, constructor: Person }; - 更稳妥的做法:
Object.defineProperty(Person.prototype, 'constructor', { value: Person, enumerable: false }),避免遍历时暴露。
为什么 constructor 重要?
它虽不参与执行逻辑,但在以下场景里确实有实际作用:
instanceof判断依赖原型链,但在调试或序列化时,常需要通过obj.constructor.name获取类型名。- 类库在做类型检查、克隆、反序列化时,经常读取
constructor来重建实例。 - ES6 class 编译成 ES5 后,Babel 等工具会主动修复
constructor,防止丢失。
注意:箭头函数没有 prototype,也没有 constructor
箭头函数不是构造函数,不能用 new 调用,因此它没有 prototype 属性,自然也不存在 constructor。试图访问 arrowFn.prototype 得到 undefined,访问 arrowFn.constructor 实际读取的是 Function.prototype.constructor(即 Function)。
