constructor属性可被修改,不绝对可靠;它默认指向创建对象的构造函数,但需通过Object.prototype.toString.call()或instanceof等更稳健方式判断类型。

可以通过实例的 constructor 属性直接访问其原始构造函数,但需注意该属性可被修改、继承或覆盖,不是绝对可靠的“溯源”方式。
constructor 属性的基本行为
每个 JavaScript 对象(除 null 和 undefined)都有一个 constructor 属性,它默认指向创建该对象的构造函数。这个属性来自对象的原型(__proto__),而非对象自身。
- 普通函数构造的实例:
new Foo()的constructor指向Foo - 字面量创建的对象(如
{}、[]、/regex/)也拥有constructor,分别指向Object、Array、RegExp等内置构造函数 - 箭头函数没有
prototype,不能用作构造函数,因此不会产生具有该constructor指向它的实例
constructor 可能失真的常见情况
constructor 不是只读属性,容易被意外或有意修改,导致无法准确还原原始构造函数:
- 手动重写原型:
Foo.prototype = { say() {} }后,new Foo().constructor会变成Object(因为新对象字面量的constructor指向Object) - 显式赋值:
Foo.prototype.constructor = Bar会让所有Foo实例的constructor指向Bar - 类继承中未修复:
class Child extends Parent默认会正确设置Child.prototype.constructor,但如果手动替换原型却忘记恢复,就会出错
更稳健的替代方案
若需可靠识别实例类型,建议结合多种方式,不单依赖 constructor:
- 使用
Object.prototype.toString.call(obj)获取内部 [[Class]] 标签,例如[object Date]、[object Promise] - 对自定义类,优先用
obj instanceof Constructor判断是否由某构造函数(或其子类)创建 - ES6+ 中可利用
obj.constructor?.name获取构造函数名(仅作参考,仍可能被篡改) - 在关键逻辑中,可为构造函数添加唯一标识(如静态 Symbol 属性),再通过实例原型链查找
修复 constructor 的典型写法
若你主动替换了原型,记得同步修正 constructor:
Foo.prototype = {
constructor: Foo, // 显式指定
method() {}
};
或更安全地用 Object.defineProperty 防止被遍历或修改:
Object.defineProperty(Foo.prototype, 'constructor', {
value: Foo,
enumerable: false,
writable: true,
configurable: true
});
不复杂但容易忽略。

















