2012-11-15 123 views
3

我最近问了一个关于for循环中延迟jquery行为的问题。 Link herefor循环中的jQuery延迟行为

我收到了一个工作答案,但我不明白它为什么有效。

如果我有以下代码:

function update(callbacks) { 
    return $.Deferred(function(dfr) { 
     setTimeout(function() { 
      callbacks.success() 
     }, 1000); 
     dfr.resolve(); 
    }).promise(); 
} 

function updateElements(deferreds) { 
    for (var i = 0; i < 5; i++) { 
     (function() { 
      var index = i; 
      deferreds.push(update({ 
       success: function() { 
        alert(index); 
       } 
      })); 
     })(); 
    } 
}; 

(function() { 
    var deffereds = []; 
    updateElements(deffereds); 
    $.when.apply($, deffereds).then(function() {}, function() {}); 
})();​ 

它通过到4返回具有值0 5个警报窗口如果我改变updateElements方法:

function updateElements(deferreds) { 
    for (var i = 0; i < 5; i++) { 
     var index = i; 
     deferreds.push(update({ 
      success: function() { 
       alert(index); 
      } 
     })); 
    } 
}; 

它返回5警报只有值为4的窗口。有人可以解释这种行为吗?我正在努力了解差异的来源。

谢谢!

+2

环路在几毫秒内运行,更新的数量,因为推迟是异步和等待,通过它显示的号码时,变量已经改变,并且该循环早已完成。通过将它包装在一个匿名函数中,index变量的值保持并且不会被更新,因为它是在每次迭代中设置的局部变量。 – adeneo

+0

[Javascript闭包内循环 - 简单实用示例]的可能重复(http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) –

回答

3

它确实是其原因是因为你已经关闭了一个循环与

(function() { 
     var index = i; 
     deferreds.push(update({ 
      success: function() { 
       alert(index); 
      } 
     })); 
})(); 

这种自我执行块变成一个静态值,因为它在没有通过外部值。正如在回答您链接,您需要传递该值。请注意IEFE(立即执行的函数表达式)末尾给出值的关键区别。对不起,大帽,但这需要强调。

(function(VALUE_ACCEPTED){ 
    //VALUE_ACCEPTED accepts the passed value of VALUE_PASSED 
})(VALUE_PASSED) 

使你的代码变得这样:

function updateElements(deferreds) { 
for (var i = 0; i < 5; i++) { 
    (function(valueAccepted) { // valueAccepted = the passed in value from i 
     var index = valueAccepted; 
     deferreds.push(update({ 
      success: function() { 
       alert(index); 
      } 
     })); 
    })(i); // pass in i to valueAccepted 
} 
};