今天在群里看到了一道經典的javascript題型,之前也遇到過,可是再次遇到時,還是做錯,還是不理解,因此這里來做個筆記吧!
不說了,直接上代碼吧
for(var i=1; i<=9; i++) {
setTimeout(function(){
console.log( i );
},1000 );
}
看到這里,你知道答案嗎?
好了,不賣關子了,答案是9個10,為什么會這樣呢?
其實原理是這樣的,這個是因為,我們在for循環中定義的變量i,在for循環結束后還沒有走出它的作用域,循環一次 定時器就會加入任務隊列,但是定時器並沒有執行。也就是說for循環之后,i依然可以訪問,值等於最后一次循環后的值,循環了9次,就有了9次定時器。因此會輸處9個10.
既然這樣,那我把上面那個for語句,稍微改一下,改成這樣呢?
現在你知道答案嗎,答案是這樣的:1、2、3、4、5、6、7、8、9然后是9個10,解答如上。
可能這里最難理解的是,setTimeout的方式(注冊事件):它有兩個參數,第一個參數是函數,第二參數是時間值。
調用setTimeout時,把函數參數,放到事件隊列中。等主程序運行完,再調用。
我們可以理解為1000之后,再放入事件隊列中,如果此時隊列為空,那么就直接調用當前函數。如果前面還有其他的事件,那就等待。
因此setTimeout是一個約會從來都不准時的童鞋
現在我再把代碼改一下,改成這樣的:
現在你又知道答案嗎?
答案是:1、2、3、4、5、6、7、8、9、0、1、2,然后是3次3,然后是9次3,其他的不說了,至於為什么是先出現3次3,然后是9次3呢?其實是因為第二個參數即時間值不一樣,所以先執行后一個時間戳
注意:調用setTimeout時,把函數參數,放到事件隊列中,等主程序運行完,再調用。即便是時間值為0,它也會等主程序執行完再執行,如果主程序隊列為空,就會直接調用。
HTML5標准規定了setTimeout()的第二個參數的最小值(最短間隔),不得低於4毫秒,如果低於這個值,就會自動增加。老版本的瀏覽器都將最短間隔設為10毫秒。而這里設置為0,其實是想表達立即執行的意思,也就是說,等當前代碼執行完(執行棧清空)以后,立即執行(0毫秒間隔)指定的回調函數。而實際上是最少4ms。