2015-09-25 126 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