0

我有两个异步函数,一个嵌套在另一个中,如下所示:

  //Async 1
  document.addEventListener("click", function(event){
     for (var i in event){
        //Async 2
        setTimeout(function(){
           console.log(i);
        }, 200*i);
     }
  });

我想要的是能够并打印对象的每个条目(ievent。然而,Firefox 上的输出是这样的:

MOZ_SOURCE_KEYBOARD
MOZ_SOURCE_KEYBOARD
MOZ_SOURCE_KEYBOARD
MOZ_SOURCE_KEYBOARD
..

如果我移到Async 2console.log(i)之外,那么我会得到正确的结果:

type
target
currentTarget
eventPhase
bubbles
cancelable
..

i为什么在读取内部async 2时它不能正常工作?event在整个Async 2代码块中也不应该“活着”吗?

4

3 回答 3

1

用这个:

document.addEventListener("click", function(event){
    var count = 1;
    for (var i in event){
        //Async 2
        setTimeout((function(i){
            return function () {
                console.log(i);
            };
        })(i), 200 * count++);
    }
});

演示:http: //jsfiddle.net/AQykp/

我不完全确定你要做什么200*i,因为i它是一个字符串(甚至不是数字)。但我试图counter在我的回答中修复它,假设你真正想要什么。

所以你看到结果的原因是因为常见的关闭问题。setTimeout回调将在循环完成后执行fori作为event. 为了克服这个问题,您必须添加一个闭包来捕获i循环中该点的值。

于 2013-04-13T00:43:19.820 回答
1

setTimeout 使用 i,因为它出现在 async1 中。也就是说,它在创建超时函数时引用 i 而不是使用 i 的值。当你的超时函数最终运行时,它会查看 i 的当前值,这是eventfor 循环之后的最后一个键。

您可以通过使用自调用函数来避免这种情况,这样该函数的参数对于 timeout 函数是本地的:

for (var i in event) {
    setTimeout((function(i) {
        return function() { console.log(i); }
    })(i), 200 * i);
}
于 2013-04-13T00:44:51.893 回答
0

事件在您的回调中确实存在。问题是,当你的函数被执行时, i 的值已经改变(从输出中我可以看到,循环已经结束并且 i 已经达到它的最大值),因此为每个回调输出相同的值.

如果您使用 Ian 注释的函数,您会将实际值 curry 到一个新函数中。这样 i 的值可以变化,您在内部函数中捕获了当前值

于 2013-04-13T00:46:17.520 回答