2015-10-20 49 views
0

我想了解我在此fiddle中重新創建的行爲。爲什麼我的基類的對象屬性與所有子類的實例共享?

function BaseObject(){} 
BaseObject.prototype.value = 1; 
BaseObject.prototype.obj = {value:1}; 

BaseObject.prototype.log = function() { 
    console.log(this.constructor.name + " - Value: " + this.value); 
    console.log(this.constructor.name + " - ObjValue: " + this.obj.value); 
}; 

BaseObject.prototype.add = function(i) { 
    this.value += i; 
    this.obj.value += i; 
}; 

function Derivation1(){}  
Derivation1.prototype = Object.create(BaseObject.prototype); 
Derivation1.prototype.constructor = Derivation1; 

function Derivation2(){} 
Derivation2.prototype = Object.create(BaseObject.prototype); 
Derivation2.prototype.constructor = Derivation2; 

var first = new Derivation1(); 
var second = new Derivation2(); 

first.log(); 
first.add(1); 
first.log(); 
second.log(); 

輸出爲:

Derivation1 - Value: 1 
Derivation1 - ObjValue: 1 
Derivation1 - Value: 2 <-- as expected 
Derivation1 - ObjValue: 2 <-- as expected 
Derivation2 - Value: 1 
Derivation2 - ObjValue: 2 <-- Why is this two too and not 1? 

的行爲表明,該對象的成員獲得由所有實例共享或靜態的方式進行訪問,而每個原始成員居住在自己的實例。

難道有人會對此有所瞭解嗎?

+1

所有內容都是按值共享的,而BaseObject.prototype.obj的值是對對象的引用。所以所有的實例都會引用同一個對象。 – Shilly

回答

0

嗯,這很簡單,真的 - 原型不是深拷貝。所有對象都具有相同的obj實例,因爲您從不爲每個對象創建新的obj

只要使用構造函數(或者一些init函數,如果您願意的話)獲取可變屬性。它將爲您節省了不少麻煩:

function BaseObject() { 
    this.value = 1; 
    this.obj = { value:1 }; 
} 

BaseObject.prototype.log = function() { 
    console.log(this.constructor.name + " - Value: " + this.value); 
    console.log(this.constructor.name + " - ObjValue: " + this.obj.value); 
}; 

BaseObject.prototype.add = function(i) { 
    this.value += i; 
    this.obj.value += i; 
}; 

function Derivation1(){ 
    BaseObject.call(this); 
} 

Derivation1.prototype = Object.create(BaseObject.prototype); 
Derivation1.prototype.constructor = Derivation1; 

function Derivation2(){ 
    BaseObject.call(this); 
} 

Derivation2.prototype = Object.create(BaseObject.prototype); 
Derivation2.prototype.constructor = Derivation2; 

var first = new Derivation1(); 
var second = new Derivation2(); 
var third = new Derivation1(); 

first.log(); 
first.add(1); 
first.log(); 
second.log(); 
third.log(); 

注意添加third實例 - 如果你將它添加到你的代碼,你會看到它共享相同obj實例。實際上,您的obj是一個「靜態屬性」 - 雖然它不是隻讀的,所以您可以在任何情況下替換它。

另一個重要的事情是,你必須手動調用父類的構造派生構造 - Object.create創建一個初始化的對象。

相關問題