2016-06-23 41 views
0

爲什麼當我在JavaScript中實例化一個新的對象作爲其屬性之一時,它總是引用同一個對象?實例化一個新的對象引用相同的屬性

例如

function test() {} 

test.prototype.state = { 
    num: 0 
}; 

var obj1 = new test(); 
var obj2 = new test(); 

obj1.state.num = 1; 

console.log(obj1.state.num,obj2.state.num); // Outputs 1 1 instead of 1 0 

而且,什麼是適當的方法,使創建新的對象屬性每次被實例化的時間?

+0

這就是原型的用途。如果它不是在原型中,而是在構造函數本身中作爲私有變量,那麼每次實例化對象時都會得到不同的結果 – Redu

回答

2

因爲這就是原型:所有實例中的共享對象。您只會明確創建一次對象,因此它只會存在一次。當實例化一個新的test時,Javascript不會爲你克隆它。通常該原型用於功能,其中這沒有任何區別。如果你想實例具體屬性,你需要在構造函數來創建它們:

function test() { 
    this.state = { num: 0 }; 
} 
+0

有趣的是,我不知道......是否有其他方法可以實現? –

+0

基本原理:沒有。當然,有許多方法可以讓你向後彎腰去做一些或多或少相似的事情,但你爲什麼這樣做?實例特定的屬性/值通過賦值給'this'而在構造函數中定義,'prototype'被所有人共享。這就是它的工作原理。 – deceze

0

我想在下面的代碼來解釋。

function test() { 
 
    var o = {a:1}; 
 
    this.geto = function(){return o.a}; 
 
    this.seto = function(v){o.a = v}; 
 
} 
 

 
test.prototype.p = {a:0}; 
 

 
var obj1 = new test(); 
 
var obj2 = new test(); 
 

 
obj1.p.a = 100; 
 
obj1.seto(50); 
 
console.log(obj1.p.a); // <- 100 
 
console.log(obj2.p.a); // <- 100 
 
console.log(obj2.geto()); // <- 1 
 
console.log(obj1.geto()); // <- 50

在第一代碼有一個封閉件,它不被共享。所有實例化的對象都有一個單獨的閉包。在原型版本中沒有閉包,並且所有實例化對象都在構造函數的原型中訪問同一個對象。

還有一個更復雜的原型閉包存在,我已經解釋了here,其中我們通過原型共享閉包本身。

0

在你的代碼中.status.num看起來屬於類,而不是實例。改變你的代碼是這樣的:

function test() { 
    this.state = {num:0};//instance property 
} 
var obj1 = new test(); 
var obj2 = new test(); 

obj1.state.num = 1; 

console.log(obj1.state.num,obj2.state.num);//1 0 as expected 
相關問題