javascript对象继承-子类和超类

javascript object inheritance - subclass and superclass

本文关键字:超类 子类 对象 继承 javascript      更新时间:2024-02-24

这两种方法之间有什么区别?

第一种方法

// Shape - superclass
function Shape() {
    this.x = 0;
    this.y = 0;
}
// superclass method
Shape.prototype.move = function(x, y) {
    this.x += x;
    this.y += y;
};
// Rectangle - subclass
function Rectangle() {
    Shape.call(this);
}
// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();

第二种方法

// Shape - superclass
function Shape() {
    this.x = 0;
    this.y = 0;
}
// superclass method
Shape.prototype.move = function(x, y) {
    this.x += x;
    this.y += y;
};
// Rectangle - subclass
function Rectangle() {
    Shape.call(this);
}
// subclass extends superclass
Rectangle.prototype = new Shape();
var rect = new Rectangle();

我看到了两个区别:一个大,一个小。

小的区别在于,在第二种方法中,Rectangle原型的constructor属性设置不正确。它将指向Shape,而不是Rectangle。这在JavaScriptOO方法中是一个非常常见的错误,大多数时候你都可以逃脱惩罚,因为人们很少使用constructor属性,但它确实存在。

最大的区别是第二个构造函数中对Shape()的额外调用。在您的特定示例中,情况或多或少是好的:Rectangle.prototype有一些额外的属性(xy,两者都等于零),这可能是您不希望它具有的,但无论如何,这些属性都会被Rectangle实例中的相应属性所掩盖。同样,这种非常常见但很小的错误,工作频率足够高,你可以逃脱惩罚

第二个方法的问题是,它只有在超类构造函数不需要任何参数时才有效。您的示例恰好符合该描述,因为它所做的只是将某些属性初始化为默认值。但是,在某些用例中,这种设置并不合适,在这些情况下不能使用第二种方法。

第二种方法的主要缺点是,它需要再调用一次Shape构造函数,以便创建一个用作Rectangle原型的对象。有不同的方法可以避免它,例如使用中间空功能:

function Rectangle() {
    Shape.call(this);
}
function f() {}
f.prototype = Shape.prototype;
Rectangle.prototype = new f();

正如你所看到的,这显然是非常笨拙的。

由于这个原因,使用CCD_ 13的模式#1被优选为更方便和有效。

然而,请注意,这两个代码段都有另一个问题:使用Shape.call(this);复制自己的属性,这也是不可取的。

主要区别在于,在第二种方法中,Shape构造函数只调用一次。在第一种方法中,不调用Shape构造函数,而是Object.create(Shape.prototype)从原型创建一个新对象。然后,可以使用Shape.call为每个子构造调用一次父构造函数。

与第二种方法一样,您仍然可以为每个子类调用Shape.call,但这会在初始原型创建过程中导致对构造函数的额外调用。

此外,对Object.create使用第一种方法会导致prototypeconstructor属性被重写,因此Rectangle.prototype.constructor = Rectangle;用于重置constructor属性。

Object.create不执行构造函数。

用New调用相当于Object.create(Object.protype)+运行构造函数。

最大的实际区别是,当您使用new时,将调用超类的构造函数,而不需要Shape.call(this);