The time is out of joint. O cursèd spite, that ever I was born to set it right!javascript
—— Hemlet Act1, Scene 5, 186-190html
let i = 0
for(i = 0; i<6; i++){
console.log(i)
}
複製代碼
Chrome運行結果 java
Firefox運行結果 segmentfault
console.log
語句放在了setTimeout
函數中且設置延時爲0,看看控制檯會輸出什麼結果?let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
// 延時函數
console.log(i)
},0)
}
複製代碼
Chrome運行結果 瀏覽器
Firefox運行結果 閉包
什麼鬼?怎麼會這樣呢!併發
setTimeout()
方法設置一個定時器,該定時器在定時器到期後執行一個函數或指定的一段代碼。
setTimeout()
方法用於在指定的毫秒數後調用函數或計算表達式異步
/* 瀏覽器3秒後向你打個招呼! */
setTimeout(
function(){
alert("Hello");
}, 3000);
複製代碼
凡是放在這個函數中東西,都過一會再作,至於過多久,能夠經過設定毫秒數來調節。 **ide
下面一部分的資料基原本自於如下這個視頻,建議你看看這個視頻,講得一級棒!( Ichiban! ) B站地址:什麼是事件循環? - Philip Roberts(視頻審覈中)函數
咱們使用一張圖來演示在調用setTimeout()時發生了什麼。不用看圖,先往下看文字。
你能夠先跳過這部分,固然,看看也無妨。
- 每當咱們調用一個函數的時候,這個函數就會被添加進調用棧並開始執行
- 正在調用棧中執行的函數若是調用了其餘函數,那麼那個函數也會被放入調用棧
- 調用棧中的函數執行完了以後,會被清出調用棧
關於調用棧的更多信息,能夠參考你不知道的JS錯誤和調用棧常識
setTimeout()
函數就是JS爲咱們提供的一個定時器。關於定時器的更多信息,能夠參考JavaScript標準參考教程 - 定時器
**
看了這麼多概念後,也許你已經一頭霧水了,不要急,接下來咱們用圖片演示一遍事件循環的過程,以後你再回來看這些定義估計會豁然開朗了。
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
複製代碼
i
,併爲它賦值,主程序開始。i<6
是否成立,須要把判斷i<6
的語句放入調用棧中執行。setTimeout()
會被扔到Web APIs中執行。i
的值,而此時i
的值爲6,因此在控制檯打印出了一個6。console.log()
,連續打印出六個6。如下代碼僅供參考,再也不解釋,由於我也不知道怎麼解釋!
i
。for(let i = 0; i<6; i++){
setTimeout(() => {
console.log(i)
}, 0)
}
複製代碼
setTimeout()
中調用。let i = 0
function cb() {
console.log(i)
}
for(i = 0; i<6; i++){
setTimeout(cb(), 0)
}
複製代碼
let i = 0
for(i = 0; i<6; i++){
(function(i){
setTimeout(() => {
console.log(i)
}, 0)
})(i)
}
複製代碼
for(var i = 1; i <= 5; i++) {
setTimeout(console.log.bind(console, i), i * 1000);
}
複製代碼
以上幾種方案的本質都是將i限制在循環中每一次建立的函數實例中,不管是藉助閉包,仍是藉助let的塊做用域,以及 Function.proptotype.bind()。
鑑於本人才疏學淺,若有錯誤之處,還望批評指正!
如何序列化JavaScript中的併發操做:回調,承諾和異步等待 - itclanCoder
關於JS的for循環包裹異步函數的問題 - microkof
JavaScript運行機制詳解:再談Event Loop - 阮一峯
【演講】What the heck is the event loop anyway? - Philip Roberts