1 回答
TA貢獻1719條經驗 獲得超6個贊
這樣其實是一下子全部打印出來的。。。不是每隔一秒打印出來。。建議這樣寫。。
for (var i = 0; i < 5; i++) {
setTimeout((function(i) {
return function() {
console.log(i);
}
})(i), i * 1000);
}
我來解釋一下這個為什么可以獲取到0、1、2、3、4.
網上關于JS預解釋的文章也不少,在進入執行上下文階段的時候函數并不會執行,簡單來說就是當你聲明這個函數的時候,只要不調用就不會執行,上下文里面只會保存著這個函數的引用,可以看做這個函數保存在內存中,只有到調用的時候函數才會執行,我說說自己的理解,有不對的地方請指出來。
如果沒有立即執行函數:
你在for循環里面實際上相當于定義了5個定時器,但是js是單線程,這五個函數會被放到隊列里面等待執行,舉個不一定恰當的例子,你就把這五個函數function() {console.log(i);}當成字符串保存到內存中,一直沒什么動靜,等到這五個函數調用執行的時候(就是setTimeout的第二個參數的時間到了的時候),才會開始執行這個函數,因為函數里面有個i,這個時候會通過作用域鏈來查找這個i,最后在外面的作用域里面查找到了i,但是這個時候for循環已經執行結束了,i已經變成4了,所以會打印出5個4.
如果有立即執行函數(比如我上面寫的那個):
你在for循環里面實際上相當于定義了5個定時器,但是js是單線程,這五個函數會被放到隊列里面等待執行。
(function(i) {
return function() { console.log(i); }})(i)
但是由于外面是立即執行函數,所以會立即就執行了,并且把i傳了進去,等到這五個函數執行的時候,向上查找i,正好在這個立即調用函數的作用域里面查找到了i,所以會打印出0、1、2、3、4.
添加回答
舉報
