這篇文章帶給大家的內容是關於深入理解JavaScript執行機制,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
首先我們大家都了解的是,JavaScript 是一門單執行緒語言,所以我們就可以得到:
JavaScript 是按照語句順序執行的首先看:
let a = '1' console.log(a) let b = '2' console.log(b)
這顯然大家都知道結果,依序輸出1,2
然而換一種:
setTimeout(function() { console.log(1) }) new Promise(function(resolve) { console.log(2) for(var i = 0;i< 10;i++){ i === 10 && resolve() } }).then(function() { console.log(3) }) console.log(4)
這時候再看程式碼的順序執行,輸出1,2, 3, 4。好了放到瀏覽器運行一下,什麼?輸出居然是 2, 4, 3,1。說好的依序執行呢?下面就需要去了解一下 JavaScript 的執行機制問題了。
首先JavaScript 是一門單執行緒的語言,在最新的HTML5 推出的 Web-worker,但是 JavaScript 是一個單執行緒的語言這一個核心還是沒有改變。所以,JavaScript 的多執行緒都是基於單執行緒模擬出來的。所以牢記 JavaScript 是單執行緒語言。
任務分為兩類:
同步任務
非同步任務
當我們開啟頁面時,頁面的渲染就是一大堆同步任務,而像載入圖片和音訊資源耗時的任務,就是非同步任務。時間循環的主要內容是:
當任務進入執行堆疊的時候,判斷是同步任務還是非同步任務,如果是同步任務,進入主執行緒執行,異步進入Event Table進行註冊函數。
當指定的事件完成後,Event Table 將這個函數移入到事件佇列
主執行緒中的任務執行完畢後,去任務佇列讀取對應的函數,進入主執行緒執行
上述的過程不斷重複,也就構成了事件循環
其中js引擎存在一個監控進程,不斷檢查主執行緒執行棧是否為空,一旦為空,就會去時間隊列那檢查有沒有等待被呼叫的函數。
例如:
setTimeout( function() { console.log(1) }, 0) console.log(2)
函數也不會立即執行的原因。不過即使主執行緒為空,0ms也是達不到的,依HTML標準,最低是4ms。 setInterval
類似的函數,對於setInterval
來說,是循環執行。對於執行順序來說,setInterval
會每隔指定的時間將註冊的函數置入Event Queue,如果前面的任務耗時太久,那麼同樣需要等待。 但是要注意的一點是,對於
來說,他並不是每過ms
執行一次,而是每過ms
會有fn
進入任務佇列。也就是說如果setInterval
的回呼函數的執行事件如果超過延遲ms
,那麼就看不出來事件間隔了。 Promise 和process.nextTick(callback)
用一段程式碼來說明:
setTimeout(function() { console.log('1'); }) new Promise(function(resolve) { console.log('2'); resolve() }).then(function() { console.log('3'); }) console.log('4');
,那麼它的回呼函數就會進入到巨集任務事件佇列中
,Promise
立即執行,輸出2,then
任務進入到微任務事件佇列中
,輸出3
console.log('1'); setTimeout(function() { console.log('2'); process.nextTick(function() { console.log('3'); }) new Promise(function(resolve) { console.log('4'); resolve(); }).then(function() { console.log('5') }) }) process.nextTick(function() { console.log('6'); }) new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { console.log('8') }) setTimeout(function() { console.log('9'); process.nextTick(function() { console.log('10'); }) new Promise(function(resolve) { console.log('11'); resolve(); }).then(function() { console.log('12') }) })
不知道大家答案是什麼?接下來我們來進行分析:
第一輪:
輸出1
進入巨集任務佇列
進入微任務佇列
然後遇到Promise
,立即執行,輸出7,then
被加入到微任務佇列
遇到第二個setTimeout
,進入巨集任務佇列
然後執行兩個微任務
執行Process.nextTick()
輸出6
執行then
,輸出8
setTimeout
console.log(),輸出2
Process.nextTick(),進入微任務佇列
Promise立即執行輸出4,
then進入微任務佇列
setTimeout,第二個
setTimeout和上述原理類似,也就不重複說明了。所以最終結果是:
1,7,6,8,2,4,3,5,9,11,10,12
以上是深入理解JavaScript執行機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!