我想在for循环中向li添加事件。
我知道什么总是出错:闭包可以访问的i
是i
的最后一个值。 i
需要锁定在关闭中。
要解决此问题,请立即使用调用函数表达式。
我不明白为什么这不起作用!
for (var i = 0; i < 10; i++){
var li = document.createElement('li');
ul.appendChild(li);
li.onclick = (function(i2){
return slideTo(i2); // slideTo is a global function
}(i));
但我知道这会奏效:
li.onclick = (function(i2){
return function(){
slideTo(i2); // slideTo is a global function
}
}(i));
为什么我需要将slideTo(i)
放入匿名函数???
这两个表达式之间的区别是什么?
非常感谢!!!
答案 0 :(得分:0)
在第一种情况下,您只需将slideTo(i2)
的值分配给onclick
:
li.onclick = (function(i2){
// Here, "i2" is **immediately** used to invoke
// slideTo(i2). It is invoked right here, in
// every loop iteration.
return slideTo(i2);
}(i));
以上将在每次循环迭代中进行评估,因此它等同于:
li.onclick = slideTo(i);
在合同中,在第二个示例中,您创建了一个正确的闭包,从而将{strong>函数(不是第一个场景中的值)分配给li.onclick
侦听器:< / p>
li.onclick = (function(i2){
// Here, "i2" is in a scope, but it's **not immediately** used.
// Instead, you are returning function which will be assigned
// to "li.onclick" but with THIS scope (i.e. scope with
// "i2" value).
//
// New scope is created in every loop iteration, but the following
// function **is not called** in a loop.
return function() {
// Later, when <li> is clicked, slideTo(i2) will be called.
slideTo(i2);
}
}(i));
答案 1 :(得分:0)
第二种形式是创建新变量绑定所必需的(即i2
) - 第一种形式是立即评估(它不会返回函数对象,它执行后面的工作),因此不是“回调”。
请记住仅新功能范围创建新变量。如果没有双闭包,您将引用相同的 i
变量。另一种方法是使用Function.bind
(它本身可以用闭包模拟)。