提問者沒有附上代碼,根據描述,我猜測代碼應當如下:
for(vari=1;i<6;i++)
{
setTimeout(function(){console.log(i);},i*1000);
}
這段循環將每隔1秒輸出一次6,那么我們來解析一下這段代碼:初始的i值為1,setTimeout將設置一個1*1000毫秒的timer,JS引擎中,timer的機制是將代碼"function(){console.log(i);}壓入隊列,等待trigger去觸發執行。但是循環代碼的執行仍然是在初始的JS線程中,沒有任何等待立即執行接下來的循環,于是壓入了2*1000一直到5*1000的5個函數,這個過程幾乎是不耗時的(循環5次對現在的CPU來說基本就是0毫秒)。所以從當前開始起計時,到1、2、3、4、5秒時均執行一次函數,在我們看來就是每隔1秒鐘輸出了一次i。
接下來看為什么輸出了5次6而不是1-5,接著上面的過程,還在JS線程當中,循環到i=5壓入timer函數后,i++仍然是要執行的,此時i的值是6,進入循環體判斷i<6失敗,循環結束。JS線程結束。
1000毫秒處的trigger觸發后,JS解釋器被傳入代碼"function(){console.log(i);}",i變量對于這個function塊來說是undefined,解釋器開始向上層塊代碼去搜索變量i,此例中只有兩層,函數的上層就是JS環境的最頂層global,global中找到變量i,其值是6,于是控制臺輸出了6;后面4次trigger觸發時原理相同,所以輸出了5次6,間隔是1秒。
為了加深理解,我們把代碼稍微修改一下:
for(vari=1;i<6;i++)
{
setTimeout((function(){console.log(i)})(),i*1000);
}
結果是瞬間輸出12345,因為(sourceCodeBlock)()這個行為是一個立即執行的行為,也就是在第一次的JS循環線程中,每一次循環就會執行一次sourceCodeBlock,它的上層塊是循環體,循環體中的i變量就是當次循環中i的值。setTimeout只是將這個閉包block執行的結果壓入了timer隊列,這個執行結果到了trigger觸發時在JS運行環境里既不是函數類型又不是表達式類型,沒有任何意義,在引擎解釋的階段就會被優化掉。因此后面的5秒鐘,瀏覽器沒有任何動作。