我见过程序员使用计数器在循环中分配事件监听器。我相信这是语法:
for(var i=0; i < someArray.length; i++){
someArray[i].onclick = (function(i){/* Some code using i */})(i);
}
有人可以解释一下这背后的逻辑,这个奇怪的语法,我从来没有见过这个:
(function(i))(i);
非常感谢您的时间和耐心。
答案 0 :(得分:7)
(function(i))(i)
语法创建一个匿名函数,然后立即执行它。
通常你会这样做,每次通过循环创建一个新函数,它有自己的变量副本,而不是每个共享相同变量的事件处理程序。
例如:
for(int i = 0; i < 10; i++)
buttons[i].click = function() { doFoo(i); };
经常抓住人,因为无论你点击什么按钮,都会调用doFoo(10)
。
鉴于:
for(int i = 0; i < 10; i++)
buttons[i].click = (function(i){ return function() { doFoo(i); };)(i);
为每次迭代创建一个内部函数的新实例(具有自己的值i
),并按预期工作。
答案 1 :(得分:5)
这样做是因为JavaScript只有功能范围,而不是阻止范围。因此,您在循环中声明的每个变量都在函数的作用域中,并且您创建的每个闭包都可以访问同一个变量。
因此,创建新范围的唯一方法是调用函数,这就是
(function(i){/* Some code using i */}(i))
正在做。
请注意,您的示例错过了一个重要部分:立即函数必须返回另一个函数,该函数将是click
处理程序:
someArray[i].onclick = (function(i){
return function() {
/* Some code using i */
}
}(i));
立即功能并不特别。它以某种方式内联函数定义和函数调用。您可以通过正常的函数调用替换它:
function getClickHandler(i) {
return function() {
/* Some code using i */
}
}
for(var i=0; i < someArray.length; i++){
someArray[i].onclick = getClickHandler(i);
}