2012-11-15 122 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 
} 
};