javascript对象继承-子类和超类
javascript object inheritance - subclass and superclass
这两种方法之间有什么区别?
第一种方法
// 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
有一些额外的属性(x
和y
,两者都等于零),这可能是您不希望它具有的,但无论如何,这些属性都会被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
使用第一种方法会导致prototype
的constructor
属性被重写,因此Rectangle.prototype.constructor = Rectangle;
用于重置constructor
属性。
Object.create不执行构造函数。
用New调用相当于Object.create(Object.protype)+运行构造函数。
最大的实际区别是,当您使用new时,将调用超类的构造函数,而不需要Shape.call(this);
。
- 是否可以从父类访问子类的属性
- 子类访问父类's闭包变量
- Javascript关键字搜索子类Div值
- 如何通过Prototype或jquery移除子类的父类基类
- JavaScript数组的子类化破坏了快速枚举
- 可以“;超级“;可以在子类的方法内部使用,在不直接引用的情况下调用相应的超类方法
- 具有子类的构造函数中的Object.freeze
- JavaScript—父类和子类/对象的此问题
- 调用子类函数时调用的超类函数
- javascript对象继承-子类和超类
- Javascript继承:从超类的方法设置子类的属性
- 我的数组子类不调用超构造函数
- Javascript:从返回超类实例的函数中设置子类原型的好处
- 如何从子类访问超类实例变量
- Prototypejs的子类不继承超类属性
- 当子类继承超类时,为什么要重置对象构造函数?
- 在Backbone.js中,如何让Model超类默认值充当子类的默认值
- 我可以实例化一个超类,并根据提供的参数实例化一个特定的子类吗
- 如何在子类中访问 getter 的超类值
- 子类如何获得超类'实例变量