2015-09-25 62 views
2

請幫我看看是什麼原因,爲什麼當地的「J」變量繼續循環過程中改變:JS封閉的可變變量

var a1 = a2 = a3 = {}; 

for (var i = 1; i < 4; i ++) { 
    (function(j){ 
    console.log(j); 
    window['a'+j].fu = function(){ 
     console.log('fu:',j); 
    }; 
    })(i); 

} 

a1.fu(); // returns "fu:,3" - why not 1? 

a2.fu(); // returns "fu:,3" - why not 2? 

a3.fu(); // returns "fu:,3" 

我讀了類似問題的很好的答案,但它不工作對我案件。 Mutable variable is accessible from closure. How can I fix this?

+1

好那是因爲你逝去的「我」的A(X).fu功能,這是「3」,在循環中它被視爲「J」。如果這是你所指的.. –

+2

問題不在於循環。 'a1','a2','a3'全都指向同一個物體。在循環的最後一次迭代中,您將'fu'的值設置爲記錄'3'的函數。你想創建三個對象:'var a1 = {},a2 = {},a3 = {};'。 –

+0

@FelixKling謝謝Felix,不知道它與PHP相比有什麼不同。現在正在工作。 – alex23

回答

5

對象分配不會複製對象,同一個對象被所有三個變量引用。所以,即使更改循環內的值,也會更新不同對象的相同位置。

在循環的最後一次迭代中將對象中的值設置爲3,並且在for循環後檢索值時,將爲所有變量返回值3。

當您創建對象

var a1 = a2 = a3 = {}; 

所有三個變量指向同一個對象。

問題的解決方案可以單獨聲明對象。

var a1 = {}, 
 
    a2 = {}, 
 
    a3 = {}; 
 

 
for (var i = 1; i < 4; i++) { 
 
    (function(j) { 
 
    console.log(j); 
 
    window['a' + j].fu = function() { 
 
     console.log('fu:', j); 
 
    }; 
 
    })(i); 
 
} 
 

 
a1.fu(); // returns "fu:,3" - why not 1? 
 

 
a2.fu(); // returns "fu:,3" - why not 2? 
 

 
a3.fu(); // returns "fu:,3"

4

您分配a1a2的方式,a3所有相同的對象是指他們都是不同的名字同樣的事情,即它們都引用同一個對象。

您的for循環然後運行三次,創建三個匿名函數。在每個函數中,j具有不同的值,所以當您撥打fu()時,您會希望運行這些函數以顯示三個不同的值。

然而,因爲a1a2a3都是一樣的,循環的每次迭代overwites以前fu(),直到你與一個與j3的內含價值只剩下。

運行有不同的分配代碼,並觀察該行爲如何改變你原本期待:

var a1 = {}; 
var a2 = {}; 
var a3 = {}; 
2

看到每一個變量就像一個指向對象: var a = b = c = {}; 等於:

a 
\ 
    \ 
b-- {} 
/
/
c 

您不使用相同的變量來訪問對象,但每次都修改相同的對象。

嘗試:

a.test = 'fromA'; 
console.log(b.test); //fromA 
console.log(c.test); //fromA