2010-06-07 71 views
5

我想要定義一個數組屬性及其子類的JavaScript類。問題是,子類莫名其妙地「共享」數組屬性的所有實例:JavaScript的繼承和陣列

// class Test 
function Test() { 
    this.array = []; 
    this.number = 0; 
} 

Test.prototype.push = function() { 
    this.array.push('hello'); 
    this.number = 100; 
} 

// class Test2 : Test 
function Test2() { 
} 

Test2.prototype = new Test(); 

var a = new Test2(); 
a.push(); // push 'hello' into a.array 

var b = new Test2(); 
alert(b.number); // b.number is 0 - that's OK 
alert(b.array); // but b.array is containing 'hello' instead of being empty. why? 

正如你可以看到我沒有這個問題的基本數據類型...任何建議?

+1

見http://stackoverflow.com/questions/1485824/javascript編程方式-inheritance-objects-declared-in-constructor-are-shared-between-inst – 2010-06-07 13:41:10

回答

1

我唯一能想到的就是數組是共享引用。應該有一個明顯的解決方案,因爲這種經典的OOP代碼始終在Javascript中實現。

4

溫你寫了Test2.prototype = new Test(),你創建了一個單一的Test實例,其中有一個數組實例,每個實例共享一個數組實例。因此,所有Test2實例共享相同的數組。

您可以通過調用Test2構造函數中的基構造函數Test來解決此問題,該構造函數將爲每個Test2實例創建一個新的數組實例。

例如:

function Test2() { 
    Test.call(this); 
} 
3

另一個,而不雅,另一種方法是從構造移動初始化代碼的方法和從兩個構造調用它:

// class Test 
function Test() { 
    this.init(); 
} 

Test.prototype.init = function() { 
    this.array = []; 
    this.number = 0; 
}; 

Test.prototype.push = function() { 
    this.array.push('hello'); 
    this.number = 100; 
}; 

// class Test2 : Test 
function Test2() { 
    this.init(); 
} 

Test2.prototype = new Test(); 
+0

+1爲清楚起見。 – jvenema 2011-03-25 12:14:41

1

JavaScript沒有一個古典繼承製度,它有一個典型的繼承製度。所以在JavaScript技術上沒有「類」的概念。

對象從其他對象(所謂的原型對象)繼承,而不是抽象類。這樣做的一個重大後果是,如果多個對象共享相同的原型,並且其中一個對象更改了原型中定義的屬性,則該更改對所有其他對象立即生效。

嘗試使用JavaScript繼承,就好像它基於類一樣,通常會引起很大的麻煩,因爲您始終都會發現此類問題。

我知道這並不能真正回答您的特定問題,但在高層次上,我建議您接受原型繼承,而不是嘗試使用「僞類」。即使它起初看起來很怪異,你的代碼將會更加可靠,並且你不會失去嘗試理解這種奇怪的錯誤的時間,這是由一連串奇怪的原型造成的。

觀看道格拉斯克羅克福德解釋繼承的視頻,它可以在Yahoo UI Theatre網站上在線獲得。它改變了我在JavaScript :)

http://video.yahoo.com/watch/111585/1027823(鏈接到第一部分)

http://developer.yahoo.com/yui/theater/(所有視頻)