2012-07-06 177 views
2
var data = [{offset: 2000, str:'foo'}, {offset: 4000, str:'bar'}]; 

for (var i=0; i<data.length; i++) { 
    var x = data[i]; 
    setTimeout(function(){printStuff(x.str)}, x.offset); 
} 

function printStuff(str) { 
    console.log(str); 
} 

我期待得到printStuff('foo')在2000毫秒偏移和printStuff('bar')在4000毫秒偏移,而是它打印「欄」兩次。我不知道發生了什麼,請幫忙。參數JavaScript回調函數

+0

這是一個範圍問題;當你的'printStuff'終於運行時,'x'已被重新分配給'{offset:4000,str:'bar'}' – jackwanders 2012-07-06 14:22:21

回答

3

這樣做:

for (var i = 0; i < data.length; i++) { 
    (function (x) { 
     setTimeout(function() { 
      printStuff(x.str) 
     }, x.offset); 
    })(data[i]); 
} 

你的問題是,X在封閉已變更的函數被調用。

2

您可以使用的功能迭代,讓一個免費的封閉:

data.forEach(function(x) { 
     setTimeout(printStuff.bind(null, x.str), x.offset); 
}); 

墊片對所有的情況下,過時的歌曲,支持是必需的:

forEach

bind

+0

我不知道這個新的和有趣的功能。你對兼容性(包括手機)有精確嗎? – 2012-07-06 14:34:42

+0

@dystroy兼容性和用戶自制代碼使這些功能在不受支持的瀏覽器中可以在我給出的鏈接中找到。大概在2009年12月之後製作/修補的任何瀏覽器都應該支持它們。 – Esailija 2012-07-06 14:35:57

0

setTimeout不阻止代碼繼續執行,因此循環完成,並在時間setTimeout執行回調,'x'的最新值是data數組中的第二個對象。