JavaScript中在循环中为数组添加函数

3

我试图在循环中使用函数创建数组。但我认为我对封装不是很了解。

例如,这段代码返回 "y y"。演示链接

HTML

<div id="result"></div>

Javascript

var json = {
            '1':'x',
            '2':'y'
           };
var my_array = [];
var div = document.getElementById('result');

for (var key in json) {
    my_array.push(function() { 
        div.innerHTML = div.innerHTML + ' ' + json[key];
    });
};

var length = my_array.length;

for (var i = 0; i < length; i++) {
  my_function = my_array[i];
  my_function();
}

我要如何获得“x y”?

非常感谢。


又一个被闭包咬的案例 - nicosantangelo
它不起作用,因为在调用函数时,key变量的值为“2”。 - Kamen Stoykov
@KamenStoykov,哦,我知道为什么它不起作用了 :) - Yevgen
只是有点好奇。为什么需要拥有一个函数数组?难道将需要使用的键或其他值的数组不更简单吗? - Frederik.L
@Frederik.L 我正在使用Ajax请求制作瀑布流。 - Yevgen
1个回答

8
由于JavaScript中闭包的工作方式,造成了这种情况。
你想要类似这样的东西:
for (var key in json) {
    (function(key) {
        my_array.push(function() { 
            div.innerHTML = div.innerHTML + ' ' + json[key];
        });
    })(key);
}

在JavaScript中,闭包或匿名函数在其定义的作用域中被词法绑定。这意味着它们可以访问在闭包所在的作用域中定义的所有变量。key最初指向1,在函数中,你有json[key],最初是json[1],也就是x。然后当循环进入下一个迭代时,你将key设置为2。但问题是第一个函数实例和第二个函数实例中的key都指向同一个位置。因此,当你最终评估函数时,它们将使用key在执行时的任何值。在执行时,key被设置为2,因为这是循环结束时key的最后一个值。
为了解决这个问题,您需要使用一个匿名的、自调用的函数来引入一个新的作用域。通过使用这种模式,您有意地引入了一个新的作用域,使得该作用域中的key具有自己的位置,并且与外部作用域中的key不同。

查看更新后的fiddle


这个不起作用... 即使您能够确定问题,提交答案之前您可能希望验证您的代码是否有效。 - taylorc93
1
@taylorc93 微小的拼写错误已经修复。 - Vivin Paliath
你不必使用匿名自调用函数来引入新的作用域。你可以通过调用一个传递必要参数并返回新函数/作用域的函数来更加简洁地实现。 - Ian
@Ian 这是另一种同样可行的方法。我想这是个人偏好的问题,但我发现使用匿名函数比调用另一个函数更符合习惯用法。你必须跳转到那个函数,这可能会有点令人不适,并导致一些上下文丢失。再次强调,这只是个人喜好的问题。 - Vivin Paliath
@VivinPaliath 非常感谢。运行良好。特别感谢您的评论。 - Yevgen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接