2011-06-15 101 views
2
var a=0; 
setTimeout (function() { animatedDraw(context, 20+32*level[0],20*0, textArray[0]); }, timeArray[0]); 
setTimeout (function() { animatedDraw(context, 20+32*level[1],20*1, textArray[1]); }, timeArray[1]); 
setTimeout (function() { animatedDraw(context, 20+32*level[2],20*2, textArray[2]); }, timeArray[2]); 
setTimeout (function() { animatedDraw(context, 20+32*level[3],20*3, textArray[3]); }, timeArray[3]); 
setTimeout (function() { animatedDraw(context, 20+32*level[4],20*4, textArray[4]); }, timeArray[4]); 
setTimeout (function() { animatedDraw(context, 20+32*level[5],20*5, textArray[5]); }, timeArray[5]); 

for (a=0; a<6; a++) 
    setTimeout (function() { animatedDraw(context, 20+32*level[a],20*0, textArray[a]); }, timeArray[a]); 

我的代碼的第一部分是工作的部分。第二部分沒有出現。我正在繪製一個畫布(HTML 5),但是當我彈出六個警報框時,警示框顯示出來。 我在做什麼非常愚蠢的錯誤?JavaScript,for循環將不起作用

在此先感謝

回答

12

的原因是,你送入setTimeout的函數都是閉包和閉包有一個持久參考他們收,較變量,而不是它們的值的副本爲什麼時候關閉創建。因此,所有這些函數都會嘗試使用相同的值a,在循環完成後(例如6)它具有的值,因此它們將失敗。

答案是讓函數關閉一些其他數據,而不會改變。通常的做法是創建一個工廠函數,它可以創建並返回所需的實際函數,讓它們關閉您提交給工廠函數(不會更改)的參數,而不是您的循環變量。例如:

for (a=0; a<6; a++) { 
    setTimeout(makeTimerFunction(a), timeArray[a]); 
} 

function makeTimerFunction(index) { 
    return function() { 
     animatedDraw(context, 20+32*level[index],20*0, textArray[index]); 
    }; 
} 

正如你可以看到,現在正由makeTimerFunction創建的功能關閉了index而非a(並且還在contextleveltextArray,你會通過那些,以及如果他們改變)。

更多關於關閉:Closures are not complicated

+0

我會接受你的答案時,我可以。謝謝,這正是我的問題!當我減少我的循環時,最後的聲明顯示。 – Hidde 2011-06-15 18:49:29

+1

@Michael:不,這沒有幫助,因爲如果它在函數內部,它在函數運行時仍然使用'a'。你需要一個工廠或類似的東西;我已經添加了一個例子。 – 2011-06-15 18:50:38

+0

@Hidde:很高興幫助。我添加了一個如何處理它的例子。 – 2011-06-15 18:51:05

2

這是很常見的JavaScript關閉問題。

你的變量a在循環繼續循環過程中發生變化,所以在回調中使用的值將是最後價值它有,而不是價值它發生在循環每次都有。

最簡單的解決方法是這樣的:

function timer_setup(a) { 
    setTimeout(function() { 
     animatedDraw(context, 20+32*level[a],20*0, textArray[a]); 
    }, timeArray[a]); 
}; 

for (a=0; a<6; a++) { 
    timer_setup(a); 
} 
0

嘗試......

for (a=0; a<6; a++) 
{ 
    (function(index) 
    { 
     setTimeout (function() { animatedDraw(context, 20+32*level[index],20*0, textArray[index]); }, timeArray[index]); 
    })(a) 
} 
+0

這將創建並丟棄每個循環的工廠函數,這是浪費。可能無害,但浪費。 – 2011-06-15 19:01:44

+0

我同意,我認爲你的解決方案要好得多。 – MillsJROSS 2011-06-15 19:18:49