2011-11-22 79 views
9

我得到下面的代碼了意想不到的結果預期:的Javascript原型屬性不會像使用數組和對象領域

var TestModel, u, u2; 

function TestModel() {} 
TestModel.prototype.a = null; 
TestModel.prototype.b = []; 

u = new TestModel(); 
u.a = 1; 
u.b.push(1); 

u2 = new TestModel(); 
u2.a = 2; 
u2.b.push(2); 

console.log(u.a, u.b);  // outputs: 1 [1,2] 
console.log(u2.a, u2.b); // outputs: 2 [1,2] 

我覺得很奇怪,u.bu2.b包含相同的值,即使的TestModel每個實例根據我如何設置原型應該有自己的實例變量。所以這是我所期待的輸出:

console.log(u.a, u.b);  // expecting: 1 [1] 
console.log(u2.a, u2.b); // expecting: 2 [2] 

同樣的事情發生,如果我設置b是一個對象,並對其設置鍵,而不是使用它作爲一個數組。我在這裏不瞭解什麼?

回答

1

該數組在兩種情況下都是相同的數組,即您設置爲原型的數組。這意味着,.push呼叫作用是陣列上,從而使所有這些都是[1, 2]

TestModel.prototype.b 
u.b 
u2.b 

他們都指的是同一個屬性。

原型通常用於功能,以便所有實例共享這些相同的功能。如果你打算修改原型屬性,那麼它們也將反映所有實例,在這種情況下,這可能是不可取的。如果實例每個都應該有一個自定義數組,那麼還要爲每個實例聲明一個自定義的實例,而不是通過原型。

13

分配值和參考他們之間有區別。

u.a = 1; 

將創建u引用的對象上一個新a屬性。在分配之前,u.a將參考TestModel.prototype.a,而是分配一個新的值實際創建實際的對象上一個新的屬性:

enter image description here

另:

enter image description here

任務後手,

u.b.push(1); 

不是創建一個新的屬性。它將引用現有的屬性數組,即TestModel.prototype.b

即使的TestModel每個實例應根據我怎麼樣了建立原型

所有實例引用相同的原型,因此它們引用的原型具有相同的屬性有它自己的實例變量。你可以很容易地看到,因爲TestMode.prototype === u.bTestMode.prototype === u2.bu.b === u2.b所有產量true

如果您分配一個新的價值,以及對u.bu2.b以及它的工作:

u.b = []; 

這通常是在構造函數中完成:

function TestModel() { 
    this.b = []; 
} 
+0

非常感謝!我並不知道這種微妙的差別。所以基本上我應該在我的構造函數中初始化所有'實例'變量,然後在其他地方操作它們。 – hiddentao

+0

@hiddentao:的確如此。可以將原始類型作爲默認值分配給原型屬性,但如果對象和數組是「每個實例」,則應在構造函數中初始化它們。我通常仍然在原型上定義屬性,但是用'null'初始化它(就像你用'TestModel.prototype.a'所做的那樣)。 –

+0

@Felix,你用什麼工具來獲得TestModel中值的漂亮圖表? –

3

原型屬性是完全相反每個實例都有自己的變量,原型的要點是所有實例自動共享相同的原型屬性,因此每個實例都不需要重新定義函數。

希望每個實例有各自爲陣這樣的:

function TestModel() { 
this.a = null; 
this.b = []; 
}