2016-11-27 63 views
3

我正在構建一個simon遊戲。在每一輪之後,玩家應該看到他在下一輪必須發揮的動作。所以我創建了一個函數showMoves,它閃爍着他必須玩的方塊。問題是這個函數沒有顯示任何東西。誰能告訴我我錯過了什麼?未能在for循環中設置超時

// the effect 
function flasher(index) { 
    $(moves[index]).fadeIn(50).fadeOut(50).fadeIn(50).fadeOut(50).fadeIn(100); 
} 
var interval2; 
// show the moves that supposed to be played 
function showMoves() { 
    for (var i = 0; i < moves; i++) { 
     if (i === 0) { 
      interval2 = setTimeout(flasher(i), 1000); 
     } else { 
      interval2 = setTimeout(flasher(i), (i+1) * 1000); 
     } 
    } 
} 
+1

你應該通過函數參考.'setTimeout(function(){flasher(i);},1000);' –

+1

@FastSnail,你仍然會有[這種情況](http://stackoverflow.com/questions/1451009/ja vascript-infamous-loop-issue),'i'變量在所有對'閃光器的調用中將是相同的' –

+1

'1000 ===(0 + 1)* 1000';除了更大的問題,這些分支是多餘的。 – Oka

回答

1

setTimeout接受函數作爲第一參數。我假設通過調用flasher你試圖避免this situation。在你的情況下,這應該是做過這樣的:

function showMoves() { 
    for (var i = 0; i < moves; i++) { 
     if (i === 0) { 
     interval2 = setTimeout(function(i) {return function() {flasher(i)}}(i), 1000); 
     } else { 
     interval2 = setTimeout(function(i) {return function() {flasher(i)}}(i), (i+1) * 1000); 
     } 
    } 
    } 
0

的setTimeout和setInterval的比我們想到他們一點點不同勢。 他們在指定的時間內保存一些事件,這些事件將在其時間內被觸發。正因爲如此,他們有循環問題:

alert(i) after 1 second 
alert(i) after 2 seconds 
alert(i) after 3 seconds 

但是,什麼是「我」的價值:

for(i=0;i<3;i++) 
{ 
setTimeout(function(){alert(i)}, i*1000); 
} 

停止循環後的瀏覽器有3個工作要做。如果你在循環結束後進行c#編程,那麼'i'將被處理掉,而我們沒有。 但JavaScript不處理'我',我們有它呢。因此,瀏覽器爲i設置當前值爲3,因爲當'i'達到3循環結束時。因此,您的瀏覽器執行此操作:

alert(3) after 1 second 
alert(3) after 2 seconds 
alert(3) after 3 seconds 

這不是我們想要的。但是,如果更改上面的代碼如下:

for(i=0;i<3;i++){ 
     (function (index) 
      { 
       setTimeout(function() { alert(index); }, i * 1000); 
      })(i); 
} 

我們將有:

alert(0) after 1 second 
alert(1) after 2 seconds 
alert(2) after 3 seconds 

所以當馬克西姆斯說你肥大使瀏覽器目前在循環得到我的價值。通過這種方式:

setTimeout(function(i) {return function() {flasher(i)}}(i), (i+1) * 1000); 

我不留下,直到循環結束,必須得到價值剛纔。

0

我可以從你的代碼派生出來的是moves是一個數組,但你使用它就好像它是for循環中的一個整數。這就是爲什麼什麼都沒有發生。

替換:

for (var i = 0; i < moves; i++) { 

有了:

for (var i = 0; i < moves.length; i++) { 

,你應該看到的事情發生。

但你會注意到flasher被立即調用,沒有超時。這是因爲flasher的結果被設置爲被調用,而不是flasher本身。
其他答案在這裏建議使用包裝函數,但這需要解決方法才能正確將索引傳遞給由setTimeout調用的函數。 所以假設它沒有在運行IE8及以下,以下是最簡潔的解決方案:

setTimeout(flasher.bind(null, i), (i+1) * 1000) 

全部工作示例:

var moves = [1, 2, 3, 4]; 
 

 
function flasher(index) { 
 
    console.log('move', moves[index]); 
 
} 
 
var interval2; 
 
// show the moves that supposed to be played 
 
function showMoves() { 
 
    for (var i = 0; i < moves.length; i++) { 
 
     interval2 = setTimeout(flasher.bind(null, i), (i+1) * 1000); 
 
    } 
 
} 
 
    
 
showMoves()