0

好的,我已经修改了大多数在 JavaScript OOP 中实现继承的技术。作为一名 Java 程序员,我对经典方法很感兴趣,但问题出在这里;说我想创建一个Animal类(我知道它不是一个真正的类,但让我使用这个术语),如下所示:

function Animal(name){  
    this.name = name;
}
Animal.prototype.getName = function() {
    return this.name;
}

重要的是要注意,这是我最初打算的一个具体类,我想实例化它,而不仅仅是将它用作超类。我可以创建几个Animal实例,每个实例都有自己的名称。

扩展此类的一种可能方法是执行以下操作:

function Cat(name, owner) {
    this.name = name;
    this.owner = owner;
}
// ALTERNATIVE 1:
    Cat.prototype = Object.create(Animal.prototype);
// ALTERNATIVE 2: 
    Cat.prototype = new Animal('LOLA');
// END OF ALTERNATIVES
Cat.constructor.prototype = Cat;
Cat.prototype.jump = function() {
    alert(this.name + " jumping");
}

使用ALTERNATIVE 1我们只是继承超类的方法,实际上我们需要重新定义nameCat 中的属性。在ALTERNATIVE 2中,实际上没有任何变化,我们只是在链中多了一个对象,该对象拥有一个name非常无用的属性:所有Cat实例都相同。

这里的重点是我已经用Animal自己的名字编写了这个类,我一扩展它就扔掉它。我想要的是一种继承属性和方法的方法,最重要的是,我希望能够重用Animal构造函数。

4

1 回答 1

0

继承基构造函数属性的传统方式如下:

function Cat(name, owner) {
    Animal.call(this, name); // call the base constructor
    this.owner = owner;
}

Cat.prototype = new Animal;
Cat.prototype.constructor = Cat;
Cat.prototype.jump = function () {
    alert(this.name + " jumping");
};

上面的代码等价于其他语言的下面的类:

class Cat extends Animal {
    constructor(name, owner) {
        super(name);
        this.owner = owner;
    }

    jump() {
        alert(this.name + " jumping");
    }
}

继承属性的新方法是完全一样的,只是我们new AnimalObject.create(Animal.prototype). 我们更喜欢新方式的原因是:

  1. 调用new Animal是不必要的开销。构造Cat函数无论如何都会再次调用它。
  2. 调用new Animal可能不会返回空白对象。它可能会为对象添加一些属性。
  3. 我们还不知道new Animal用什么参数来调用。因此,调用它是没有意义的。

因此,现在首选的继承方式是:

function Cat(name, owner) {
    Animal.call(this, name); // call the base constructor
    this.owner = owner;
}

Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.jump = function () {
    alert(this.name + " jumping");
};

请注意,调用基本构造函数很重要,因为它可能会进行一些初始化,这是实例正常工作所必需的。

如果您对以经典风格编写 JavaScript 代码感兴趣,请查看以下描述原型类同构的答案。以下代码取自上述答案:

function CLASS(prototype, base) {
    switch (typeof base) {
    case "function": base = base.prototype;
    case "object": prototype = Object.create(base, descriptorOf(prototype));
    }

    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

function descriptorOf(object) {
    return Object.keys(object).reduce(function (descriptor, key) {
        descriptor[key] = Object.getOwnPropertyDescriptor(object, key);
        return descriptor;
    }, {});
}

使用该CLASS函数,我们可以在 JavaScript 中定义伪类,如下所示:

var Animal = CLASS({
    constructor: function (name) {
        this.name = name;
    },
    getName: function () {
        return this.name;
    }
});

var Cat = CLASS({
    constructor: function (name, owner) {
        Animal.call(this, name);
        this.owner = owner;
    },
    jump: function () {
        alert(this.name + " jumping");
    }
}, Animal);

还有其他方法可以在 JavaScript 中进行继承。我建议你阅读我关于原型继承为何重要的博文,以了解更多关于 JavaScript 中的继承的信息。

于 2013-08-14T01:34:00.387 回答