我假设您想知道为什么必须在构造函数中和构造函数内部提供name参数。Emperorthis.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);
}