从继承类的ctor调用父ctor

时间:2014-07-17 13:26:41

标签: javascript prototypal-inheritance

是否有效而不是这样做

function Animal(name, numLegs) {
    this.name = name;
    this.numLegs = numLegs;
}
Animal.prototype.sayName = function() {
    console.log("Hi my name is " + this.name);
};
function Penguin(name) {
    this.name = name;
    this.numLegs = 2;
}
Penguin.prototype = new Animal();
var penguin = new Penguin("Tux");
penguin.sayName();

那样做?

function Animal(name, numLegs) {
    this.name = name;
    this.numLegs = numLegs;
}
Animal.prototype.sayName = function() {
    console.log("Hi my name is " + this.name);
};
function Penguin(name) {
    return new Animal(name, 2);
}
Penguin.prototype = new Animal();
var penguin = new Penguin("Tux");
penguin.sayName();

我发现第二个版本更优雅,希望两个版本的结果相同,但第二个版本codeacademy告诉我

Oops, try again. Make sure to create a new Penguin instance called penguin!

而第一个被接受。

3 个答案:

答案 0 :(得分:1)

我认为不同之处在于构造函数不会返回值。所以,如果你打电话

new Penguin('bla')

返回新对象的不是Penguin函数,而是返回新Object的 new 。因此,如果你让Penguin()返回一个新的Object,这将与new-keyword相冲突。

如果要调用父构造函数,可以按如下方式执行:

function Penguin(name) {
   Animal.call(this, name, 2);
}

另外:当你将Animal的原型分配给它的子原型企鹅时,你可以在没有参数的情况下调用你的例子中的函数。有一种更简洁的方法:

Penguin.prototype = Object.create(Animal.prototype);

之后你丢失了Penguin的构造函数,所以你需要像这样重新分配它:

Penguin.prototype.constructor = Animal;

这里有详细解释: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript

答案 1 :(得分:1)

这不是调用父构造函数的正确方法:

function Penguin(name) {
    return new Animal(name, 2);
}

正确的方法如下:

function Penguin(name) {
    Animal.call(this, name, 2);
}

原因在于new的工作方式:

  1. 我们假设您有一个名为ABC的函数。
  2. 执行new ABC时,JavaScript会创建ABC.prototype的实例,并将其绑定到函数this内的ABC,这就是为什么可以向{{1}添加属性的原因} {} this
  3. 构造函数默认返回ABC ,除非您明确返回另一个对象。
  4. Codecademy抱怨您的代码的原因是因为您返回的this new Animal(name, 2) instanceof

    正如我之前所说,调用父构造函数的正确方法是使用Penguin。在这种情况下,我们将父构造函数中的ParentConstructor.call(this, arg1, arg2, ...)设置为与当前构造函数(由this创建的实例)中的this相同的值。


    如果您想编写优雅的代码,请尝试使用以下尺寸:

    new

    使用function defclass(prototype) { var constructor = prototype.constructor; var instance = prototype.instance = function () {}; constructor.prototype = instance.prototype = prototype; return constructor; } function extend(parent, keys) { var supertype = keys.super = parent.prototype; var prototype = new supertype.instance; for (var key in keys) prototype[key] = keys[key]; return defclass(prototype); } defclass,您可以按如下方式重写代码:

    extend

    那有多酷?

答案 2 :(得分:0)

在第二个示例中,您不会返回Penguin的实例,而是返回Animal的实例。如果你想为penguin添加更多功能,你需要使用额外的功能来装饰Animal类。

function Penguin(name) {
    var self = new Animal(name, 2);
    self.penguinFunction = function (){
        //do something here
    }
    return self;
}