大家先不要看後面的內容,先看下面這段簡短的代碼,想象i應該彈出的是多少呢?
var t=null;var i=0;function a(){ i++; if(i==20){ return; } t=setTimeout(a,17);}a();alert(i);
這就是今天我寫效果的時候遇到一個問題,當我設定一個定時器做迴圈的時候,下面的程式不等我的迴圈結束就開始運行了。
上段程式的答案是"1"。
那麼為什麼程式沒等迴圈完畢就著急地開始運行alert(i)了呢,原因就出在setTimeout的原理上。
其實setTimeout和setInterval這兩個定時器一旦觸發,就是和js程式並存執行的,也就是他們並不在一個時間軸上。計時器的作用是僅僅是做一個計劃,那就是每隔一段時間執行一次目標方法。
比如我們做個周計劃每周末都出去玩,這其實就是一個定時器,每隔七天出去玩一次。但是周一到周五還是要上班的,也就是說我們不能因為周末出去玩就周一到周五不干事了。
js程式也是這樣的,計時器的任務我每到那個時間點會完成,但是其它時間我會繼續執行下面的代碼。如上程式,a函數運行到定時器前一句的時候,i的值是1,然後執行定時器,17毫秒遠遠大過程式的已耗用時間,於是js不等了繼續執行,於是alert(i),也就是1。
為了證明計時器沒有偷懶,我們每隔一段時間彈出一次i,如下程式:
var t=null;var f=null;var i=0;function a(){ i++; if(i==20){ return; } t=setTimeout(a,17);}function b(){ alert(i); f=setTimeout(b,17);}a();b();
可以發現i的確是從0加到了20。
以上囉嗦總結成一句話,那就是定時器和js其他程式是並存執行的,互不影響!
於是開頭的程式正確的寫法應該是這樣的:
var t=null;var i=0;function a(){ i++; if(i==20){ alert(i); return; } t=setTimeout(a,1);}a();
在程式出口的地方做操作,就可以正確地彈出i了(i=20)。