![](/img/trans.png)
[英]JavaScript inheritance, superclass identifier in subclass is not defined, even though it is
[英]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
。 這是JavaScript OO方法中的一個非常普遍的錯誤,大多數時候您都可以避免使用它,因為人們使用的不是很多的constructor
屬性,但是它就在那里。
最大的不同是在第二個構造方法中對Shape()
的附加調用 。 在您的特定示例中,事情或多或少都可以正常運行: Rectangle.prototype
具有一些您可能不希望擁有的額外屬性( x
和y
,它們都等於零),但是這些屬性將被它們遮蓋。 Rectangle
實例中的相應屬性。 同樣,這是一種非常常見但很小的錯誤,經常起作用,足以使您擺脫它。
第二種方法的問題在於,它僅在超類構造函數不需要任何參數時才起作用 。 您的示例恰好適合該描述,因為它所做的只是將某些屬性初始化為默認值。 但是在某些用例中,這種設置並不十分合適,並且在這種情況下不能使用第二種方法。
主要區別在於在第二種方法中, Shape
構造函數僅被調用一次。 在第一種方法中,不調用Shape
構造函數,而是Object.create(Shape.prototype)
從原型創建一個新對象。 然后可以通過Shape.call
每個子構造調用一次父構造函數。
與第二種方法一樣,您仍然可以為每個子類調用Shape.call
,但是它會在初始原型創建期間對構造函數進行額外的調用。
同樣,將第一種方法與Object.create
會導致prototype
的constructor
屬性被覆蓋,因此Rectangle.prototype.constructor = Rectangle;
用於重置constructor
屬性。
第二種方法的主要缺點是,它需要對Shape
構造函數進行一次額外的調用,才能創建一個對象用作Rectangle
原型。 有不同的方法來避免它,例如,使用中間空函數:
function Rectangle() {
Shape.call(this);
}
function f() {}
f.prototype = Shape.prototype;
Rectangle.prototype = new f();
如您所見,這顯然很笨拙。
因此,首選使用Object.create
模式#1更為方便和有效。
但是請注意,兩個片段都有另一個問題:自己的屬性是用Shape.call(this);
復制的Shape.call(this);
這也是不希望的。
Object.create不執行構造函數。
使用New調用等效於Object.create(object.prototype)+運行構造函數。
最大的實際區別是,當您使用new時,將調用超類的構造函數,而無需Shape.call(this);
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.