2012-02-27 46 views
5

我理解JavaScript語言的以下屬性定義的變量:的JavaScript混淆參照VS值

var bar = 1; 
var foo = bar; 
bar = "something entirely different"; 
// foo is still 1 

但是,試圖這樣的邏輯應用到對象時,似乎採取不同的行動:

var bar = {}; 
bar.prop = 1; 
var foo = bar; 
bar.prop = "something entirely different"; 
// foo.prop now changes to "something entirely different" 
// but... 
bar = "no longer an object"; 
// now foo remains an object with the prop property 

有人可以告訴我發生了什麼,爲什麼有區別?

+3

我可能已經回答了我自己的問題: 「JavaScript總是按值傳遞,但是當一個變量引用一個對象(包括數組)時,」值「是對該對象的引用。 但這仍然令人困惑,有人可以解釋更多? – Jeff 2012-02-27 22:50:58

+0

看我的答案傑夫,請讓我知道,如果這是有道理的? – Josh 2012-02-27 22:52:06

+0

可能的重複[是Java通過引用?](http://stackoverflow.com/questions/40480/is-java-pass-by-reference) – 2012-02-27 22:57:13

回答

1

這是正確的。當你將一個變量賦值給一個對象時,你真的創建了該對象的第二個引用。在第一種情況下,你在做什麼是指派bar在字符串foo分點,但隨後你改變什麼bar點的時候重新分配bar來。

在第二個例子,可以分配給bar一個新的對象,則指向foo以相同的對象,則重新分配bar爲字符串。 foo仍指向同一個對象。

認爲它是這樣的:bar = "something"改變什麼bar,不改變實際的對象{}爲字符串。

This article對你所看到的是一個相當好的解釋。然而,我正在尋找更好/更權威的參考資料。

+1

這就是我要說的,包含對象'bar'的內存被分配給不被擦除,並且被替換爲不再是對象「,但是引用被丟棄(並且如果它沒有其他引用,它會排隊等待垃圾收集)。 – 2012-02-27 22:54:41

0

在第一個代碼中,將Var欄定義爲變量。

在您將其定義爲對象的第二個代碼中。

變量佔據了內存中的一個位置;所以當你從bar定義foo時,它將和變量一樣,並保留一個新的內存位置;當你使用相等的運算符時,你正在替換這個變量的數據內容。

初始化的第二個示例代碼中的對象將指向(將作爲指針)指向將包含此對象的數據的內存位置;當你從bar中定義foo時,它將與對象的類型相同,並指向相同的內存位置;所以改變這兩個參考對象值中的一個將反映在另一個參考對象值上。

1

讓我們把它一行一行:

var foo = bar; 

所有這些對象的名稱做的是在內存中保留的地址。因此,在此聲明中,您使foo保持與bar相同的內存地址。例如,如果bar保持0xFF,則通過賦值foo也保持0xFF。

但是,請記住barfoo是兩個不同的對象,它們碰巧只是在內存中保存相同的地址。

現在,由於它們碰巧在內存中保存了相同的地址,所以bar的變異成員也會影響foo的成員,因爲它們綁定到同一個對象。

bar.prop = "something entirely different"; // affects foo.prop also 

然而,這裏很關鍵的一點要記住:

Assignment only changes what the name of the object is bound to, and does not affect any other objects.

換句話說,下面的語句做bar持有不同的內存地址,但是這並不影響foo。現在

bar = "no longer an object"; // Made bar hold a different memory address 

,說明報價:

Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.

拿這個例子:

function f(obj1, obj2) 
{ 
    obj1.prop = 10; 
    obj2 = {prop: 20}; 
} 

var bar = {prop: 1}; 
var foo = {prop: 2}; 
f(bar, foo); 
console.log("bar.prop: " + bar.prop + ", foo.prop: " + foo.prop); 

這將打印出局:bar.prop: 10, foo.prop: 2。在內部函數f中,obj1保存與bar相同的內存地址,obj2保存與foo相同的內存地址。但是,只有欄受到影響,因爲f內只反映對象的變更成員,而賦值obj2 = {prop: 20};僅影響局部變量obj2而不影響foo

換句話說,the "value" is a reference to an object表示改變成員影響對象對象,但分配隻影響局部變量。

+0

我認爲這是我見過的最令人困惑的解釋。忘記所有關於內存和地址的內容,ECMA-262指定了行爲,而不是實現。 – RobG 2012-02-28 00:18:22

+0

@RobG:我認爲具體而不是抽象對我來說更有意義(這正是我想要做的),但是感謝評論(我意識到這種方式可能並不適合所有人)。但是,更多*特定*評論對我來說會更有益處。 – 2012-02-28 01:02:17