2012-05-08 135 views
0

我不明白爲什麼數組在兩個實例之間共享,而原始類型不是。有人可以解釋嗎?參考和原始原型值

MyObject = function() {}; 
MyObject.prototype = {anArray : [],aString : ''}; 
var c1 = new MyObject(); 
c1.aString = 'a'; 
c1.anArray.push('a'); 
var c2 = new MyObject(); 
console.log(c2.aString); 
console.log(c2.anArray); 
+0

原始類型* *在兩個實例之間共享,但您已覆蓋'c1'對象的自己的值。 – zzzzBov

回答

0

當分配

c1.aString = 'a' 

分配給原型的aString領域。一個名爲aString的新字段直接在c1對象中創建,並隱藏原型中的aString字段。

同時,當你調用

c1.anArray.push('a'); 

存在c1沒有anArray領域,所以你引用的原型anArray。您可以通過執行

c1.anArray = new Array(); 

測試這一點,並指出,一個新的屬性anArrayc1被創建,不與原型anArray干擾。在這種情況下,

console.log(c1.anArray); 
console.log(c2.anArray); 

會有不同的結果,因爲c2仍然會參考anArray原型。

如果在對象和原型中(甚至在原型鏈中)直接存在具有相同名稱的字段,並且您請求此字段的值,則解釋器首先直接查看對象,只有原型鏈,直到它找到某個地方的領域。

但是,如果爲字段賦值,它總是直接在對象中完成,而不會在其原型中完成。

2

字符串是不可變的,數組是可變的。您正在替換字符串,但修改陣列。

如果你在上覆蓋而不是修改它,你會得到與數組和字符串相同的行爲。

MyObject = function() {}; 
MyObject.prototype = {anArray : [],aString : ''}; 

var c1 = new MyObject(); 
c1.aString = 'a'; 
c1.anArray = [] 
c1.anArray.push('a'); 

var c2 = new MyObject(); 
console.log(c2.aString); // '' 
console.log(c2.anArray); // [] 

所以它纔有意義,以把一個對象或陣列上的prototype如果你在允許所有情況下,觀察變化的IT規劃。否則,直接把它放在實例上。

MyObject = function() { 
    this.anArray = []; 
}; 
MyObject.prototype = {aString : ''}; 
+0

感謝您的回覆。那麼有什麼推薦的方法來實現可變實例變量呢? –

+0

@bradmiley:將數組保持原型,並將其直接賦值給構造函數中的新對象。 –