2013-12-10 183 views
1

我有我可以不解決,因爲我無法解釋這種現象的一個問題:對象屬性在原型

var A = function(value) { 
    this.prop = value; 
}; 

A.prototype = { 
    prop: 0 
}; 

var a = new A(1); 
var b = new A(2); 

console.log(a.prop); 
console.log(b.prop); 

輸出:

1 
2 

但是,與此代碼(幾乎是相同的):

var A = function(value) { 
    this.prop.value = value; 
}; 

A.prototype = { 
    prop: { 
     value: 0 
    } 
}; 

var a = new A(1); 
var b = new A(2); 

console.log(a.prop.value); 
console.log(b.prop.value); 

我有這樣的輸出:

2 
2 

有人可以解釋我嗎? 謝謝...

編輯:

這裏有一個解決方案:

var A = function(value) { 
    this.prop = {}; 
    this.prop.value = value; 
}; 

A.prototype = { 

}; 

var a = new A(1); 
var b = new A(2); 

console.log(a.prop.value); 
console.log(b.prop.value); 
+0

你是變異的共享對象(不同誘變是當你重新分配子屬性或調用改變對象的功能)。道具是共享的,因爲它在原型上,並且你不重新賦值它(prop = newValue),如果你重新賦值它,那麼道具會被實例(a和b)遮蔽。更多關於原型和構造函數在這裏:http://stackoverflow.com/a/16063711/1641941 – HMR

回答

1

在示例1中,this.prop原始類型,該值由值引用,因此不在實例之間共享。

在實施例2,this.prop對象參考從原型從一個單一的對象進行初始化,所以這個單一目的通過所有實例共享。

在上一個「示例」解決方案中,您使用= {}創建了一個新對象,因此所有實例都有自己的對象。

更多關於原始類型的詳細信息:Primitive value vs Reference value

+0

更正確:它並不重要如果A.prototype.prop是原始對象或對象。當使用this.prop在構造函數中賦值時,prop值將被遮蔽。第二個例子不重新分配它,但改變它。由於原始圖不能被改變,所以改變它們的唯一方法是重新賦值,從而對其進行投影。在示例1中,prop值也是如下面的答案所示:http://stackoverflow.com/a/16063711/1641941 – HMR

1

原型創建只有一次,這只是一個簡單的對象,其孩子的連接它屬於一個函數的所有實例。

所以它基本上是一樣的,如果你寫:

var obj = { value: 0 }; 

var a = {}, b = {}; 

a.obj = obj; 
b.obj = obj; 

obj.value = 2; 

,你可以看到兩個a.objb.obj引用相同obj兩者a.obj.valueb.obj.value2在這個例子中

1

思考作爲屬性在所有實例之間共享的原型屬性。
然而你可以在每個實例上覆蓋它,這就是你在第一個例子中所做的。
一旦在每個實例中重寫,您不再使用obj.prop訪問原型屬性,該屬性現在引用實例屬性。您需要使用obj.prototype.prop再次閱讀它,但是這種語法是非法的:您可以使用obj.__proto__.prop(非標準)或Object.getPrototypeOf(obj).prop(EcmaScript 5)來執行此操作。
在第二個實例中,您不要更改構造函數中的屬性:而是更改此屬性的屬性。所以兩個構造函數都訪問同一個對象,然後改變它的一個屬性值,所以最後設置它將會'取勝'。這裏原型屬性並未被實例屬性覆蓋('隱藏'),而是實際訪問obj.prototype.prop訪問obj.prop。

1

發生這種情況是因爲在JS中,對象是通過引用傳遞的,而原語不是。

由於原型在2個實例之間共享,因此修改其上的對象將更新所有實例。

+1

在JS對象傳遞BY VALUE這是一個參考 - 有一個細微差別 – Adassko