为什么我们需要在闭包中传递一个新变量

时间:2015-05-25 17:31:22

标签: javascript closures

我正在阅读http://javascriptissexy.com/understand-javascript-closures-with-ease/,我对这行代码有疑问。

请注意,出于格式化目的,我删除了原始代码中的注释

function celebrityIDCreator (theCelebrities) {
var i;
var uniqueID = 100;
for (i = 0; i < theCelebrities.length; i++) {
    theCelebrities[i]["id"] = function (j)  { 
        return function () {
            return uniqueID + j; 
        } () 
    } (i); 
}

    归还名人; }

我看到j意味着在函数中传递i的值,但我不明白为什么我们不能只使用“i”所以代码读起来像这样

theCelebrities[i]["id"] = function (i) {
return function () {
    return uniqueID+ i;
} ()

每次,uniqueID都会捕获循环中更新的“i”值。

有人可以解释为什么有必要创建变量j而不仅仅是传递i?

3 个答案:

答案 0 :(得分:0)

在失败的情况下(直接捕获i),当一个闭包捕获i时,它会捕获对它的引用,而不是副本。

因此,当闭包中的代码运行时,它在闭包代码运行时使用i 的值,而不是在创建闭包时。在关闭代码运行时,i的值为theCelebrities.length,因为循环已经完成。

在工作案例中(通过i捕获j的值),i的值在关闭时转移到j 已创建,因此对i的后续更改不会对闭包产生任何影响。

答案 1 :(得分:0)

这与javascript中的变量范围有关。

当你这样做时

return function () {
    return uniqueID+ i;
}

匿名函数看到i,它在for循环中递增。执行匿名函数时,i将是最后一个迭代值。在循环中可以看到i并保存在匿名函数中。

然而,当你这样做时

function (j)  { 
        return function () {
            return uniqueID + j; 
        } () 
    } (i); 

您正在创建一个仅对匿名函数可见的新范围。这就是你必须传入它的原因。匿名函数将在传入时使用j。进一步的迭代将使j不受影响。

答案 2 :(得分:0)

您也可以使用parametersarguments来思考,就像通常使用其他任何编程语言一样。所以,回答这个问题:

  

为什么我们不能只使用&#34; i&#34;所以代码读起来像这样

theCelebrities[i]["id"] = function (i) {
    return function () {
        return uniqueID+ i;
    } ()

你不能,因为函数(i)中的i是一个形式参数,而不是参数。在这种情况下:

... = function (j)  { 
    return function () {
        return uniqueID + j; 
    } () 
} (i); 

i是一个论点。这正是您希望为您的函数提供的功能。