javascript 中的函数实际上是对象。当我们在 Javascript 中创建任何函数Foo
时,解释器会自动创建一个prototype
属性Foo.prototype
,它本身就是一个对象。然后解释器constructor
在这个对象上创建一个引用Foo
自身的属性:
console.log(Foo.prototype.constructor); // reference to Foo;
console.log(Foo.prototype.hasOwnProperty("constructor")); // TRUE;
当我们创建Bar
函数时,也会发生同样的过程。但稍后我们会介绍一个不同之处。不同之处在于我们Bar.prototype
使用以下代码手动覆盖对象:
Bar.prototype = Object.create(Foo.prototype);
现在Bar.prototype
有一个我们手动创建的新对象。这个新对象没有constructor
属性,因为它是由我们而不是解释器创建的:
console.log(Bar.prototype.hasOwnProperty("constructor")); // FALSE
所以Bar.prototype
没有自己的constructor
财产,但Foo.prototype
有。接下来,假设我们创建了一个实例Bar
:
var myBar = new Bar();
myBar.constructor
是对象上不存在的继承属性myBar
。如果我们尝试访问它,javascript 解释器会在原型链中搜索该constructor
属性。它没有找到一个,Bar.prototype
因为我们覆盖了那个对象。解释器继续搜索并最终在 上找到属性Foo.prototype
。因此,任何对 的引用都myBar.constructor
将引用Foo.prototype.constructor
,其中包含对 的引用Foo
:
console.log(myBar.constructor); // reference to Foo
所以这就是我们显式Bar.prototype.constructor
手动设置的原因,这样当遍历原型链时,解释器会找到一个constructor
属性 on Bar.prototype
,就像我们没有覆盖它一样:
Bar.prototype.constructor = Bar;
最终结果是我们的对象有更有用的行为:
var myBar2 = new Bar();
console.log(myBar2.constructor); // reference to Bar
这个问题不应该经常出现,因为很少有人需要检查constructor
对象的属性。