当您将函数分配给单击处理程序时,将创建一个闭包。
基本上,当您嵌套函数时会形成一个闭包,即使在其父函数已经执行之后,内部函数也可以引用其外部封闭函数中存在的变量。
在执行 click 事件时,处理程序引用i变量的最后一个值,因为该变量存储在闭包中。
正如您所注意到的,通过包装单击处理程序函数以接受i变量作为参数,并返回另一个函数(基本上是创建另一个闭包),它按您的预期工作:
for ( var i = 0; i < 4; i++ ) {
var a = document.createElement( "a" );
a.onclick = (function(j) { // a closure is created
return function () {
alert(j);
}
}(i));
document.getElementById( "foo" ).appendChild( a );
}
当您迭代时,实际上创建了 4 个函数,每个函数i在创建时存储一个引用(通过传递i),这个值存储在外部闭包中,当点击事件触发时执行内部函数。
我使用下面的代码片段来解释闭包(以及curry 的一个非常基本的概念),我认为一个简单的例子可以更容易地理解这个概念:
// a function that generates functions to add two numbers
function addGenerator (x) { // closure that stores the first number
return function (y){ // make the addition
return x + y;
};
}
var plusOne = addGenerator(1), // create two number adding functions
addFive = addGenerator(5);
alert(addFive(10)); // 15
alert(plusOne(10)); // 11