与闭包混淆以及为什么返回不正确的值

时间:2014-11-13 21:03:00

标签: javascript closures

我以为我对封闭有一个体面的理解然后我的朋友给了我一个问题来解决涉及闭包(我当时不知道)。这是代码块:

function fixMe() {
   var numbers = [];
   var i = 0;
   for (; i < 10; i++) {
     numbers[i] = function () {
        return i;
     };

   }
   return numbers;
}

所以当我打电话时:

var numbers = fixMe();
alert(numbers[2]());

即使我在i函数中将fixMe()作为参数,它也始终会发出警告。

Here是其中的一员。

他告诉我的解决方案最终是:

function fixMe() {
    var numbers = [];
    var i = 0;

    for (; i < 10; i++) {
        numbers[i] = function (i) {
            return function () {
                return i;
            };
        }(i);
    }

    return numbers;
}

var numbers = fixMe();
alert(numbers[2]());

Jsfiddle解决方案。我尝试了很多东西,但从未得出结论我需要嵌套函数。

目前,我不明白为什么第一个函数会返回一个总是返回10的函数数组。我假设这是闭包问题?第二,为什么同一个函数在另一个函数中解决问题?看起来需要在函数创建结束时(i),但如果在没有嵌套函数的情况下添加它,它甚至都不会编译。到底是做什么的?还有另一个更简单的解决方案吗?

这可能是很多问题,但我觉得如果他们得到答案,他们对我对javascript中的闭包的理解都会有所帮助。

1 个答案:

答案 0 :(得分:4)

第一个版本(破碎的版本)创建了一组功能,这些功能全部共享完全相同的变量i。也就是说,数组中的每个函数都保留对该(单个)变量i的访问权限。它不是i值的副本 i

在循环结束时,变量i的值是多少?它是10。当你稍后调用函数时,这就是你得到的值。

现在,在第二个版本中,插入函数复制i的值并将其存储到每次迭代时新创建的本地(闭包)变量中。它是一个独特的闭包,因为每次迭代都有一个对匿名包装函数的独特函数调用。函数调用(就像任何其他JavaScript函数调用一样)将外部i的值的副本传递给匿名函数,此后该副本将永远不会更改。因此,数组中的每个函数现在都有一个私有i,因此解决了前一个问题。