我假设您想知道为什么必须在构造函数中和构造函数内部提供name
参数。Emperor
this.name = name;
JavaScript 中的原型继承非常简单,没有隐藏的魔法。Emperor
您在和之间提供的唯一连接Penguin
是在这一行:
Emperor.prototype = new Penguin();
Emperor.prototype
现在是 的一个实例Penguin
,但它可以是任何对象。该函数 Emperor
对该函数一无所知Penguin
,因此它不会神奇地调用Penguin
。
当你用 调用函数 ( Func
) 时new
,它所做的只是创建一个新的空对象,其原型是函数prototype
属性 ( Func.prototype
)。该对象将成为this
构造函数内部的值,如果没有返回其他对象,将隐式返回。
但是从 Penguin 类构造函数继承的名称呢?它去哪儿了?
它是每个实例的属性的一个属性,Emperor.prototype
并被每个Emperor
实例的name
属性所遮蔽。
看看我的回答,我在这里创建了一些很好的 ASCII 图表来解释实例和它们的原型之间的关系。
注意: Emperor.prototype = new Penguin();
实际上不是建立继承的好方法。如果Penguin
需要 参数会发生什么?什么会通过?
此时你其实并不想创建 的新实例Penguin
,只想将Penguin
'挂接prototype
到原型链中。您可以通过以下方式轻松做到这一点Object.create
:
Emperor.prototype = Object.create(Penguin.prototype);
Emperor.prototype.constructor = Emperor;
但随后新Emperor
对象将不再具有numLegs
属性。这就是为什么您必须Penguin
在每个新Emperor
实例上调用 ,就像在其他语言中一样super()
:
function Emperor (name){
Penguin.call(this, name);
}