我正在阅读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?
答案 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)
您也可以使用parameters
和arguments
来思考,就像通常使用其他任何编程语言一样。所以,回答这个问题:
为什么我们不能只使用&#34; i&#34;所以代码读起来像这样
theCelebrities[i]["id"] = function (i) {
return function () {
return uniqueID+ i;
} ()
你不能,因为函数(i)中的i
是一个形式参数,而不是参数。在这种情况下:
... = function (j) {
return function () {
return uniqueID + j;
} ()
} (i);
i
是一个论点。这正是您希望为您的函数提供的功能。