可变变量的JS闭包

时间:2015-09-25 15:56:47

标签: javascript closures mutable

请帮助我找到循环期间本地“j”变量继续变化的原因:

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?

3 个答案:

答案 0 :(得分:5)

对象赋值不会复制对象,所有三个变量都会引用相同的对象。因此,即使更改循环内的值也会更新不同对象的相同位置。

在循环的最后一次迭代中,对象中的值设置为3,并且在for循环后检索值时,将为所有变量返回值3。

创建对象时

var a1 = a2 = a3 = {};

所有三个变量都指向同一个对象。

问题的解决方案可以单独声明对象。

&#13;
&#13;
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"
&#13;
&#13;
&#13;

答案 1 :(得分:4)

您将a1a2a3全部分配给同一个对象的方式意味着它们对于同一个事物都是不同的名称,即它们所有人都引用同一个对象。

然后你的for循环运行三次,创建三个匿名函数。在每个函数中,j具有不同的值,因此当您调用fu()时,您希望运行这些函数以显示三个不同的值。

但是,由于a1a2a3都是相同的,因此循环的每次迭代都会覆盖之前的fu(),直到您只使用嵌入值j3的那个。

运行具有不同赋值的代码,并观察行为如何更改为您最初期望的内容:

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

答案 2 :(得分:2)

将每个变量视为指向对象的指针: var a = b = c = {}; 等于:

a
 \
  \
b-- {}
  /
 /
c

您不能使用相同的变量来访问该对象,但每次都修改同一个对象。

尝试:

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