摘要:說運行機制之前,先看一段代碼如果你看到這段代碼,并知道正確的輸出順序。執行棧執行棧也就是常說的調用棧,它是一種擁有后進先出的數據結構。事件循環是單線程的,也就是說它一次僅能處理一個任務。好了,最后的結果就是。
說javascript運行機制之前,先看一段代碼:
console.log(1) Promise.resolve().then(function () { console.log(2) }) new Promise(function(resolve, reject){ console.log(3) resolve() }).then(function () { console.log(4) setTimeout(function () { console.log(5) }) }) console.log(6) setTimeout(function () { Promise.resolve().then(function () { console.log(7) setTimeout(function () { console.log(8) }) }) })
如果你看到這段代碼,并知道正確的輸出順序。那說明你對這塊掌握的差不多了。(直接翻到最后看結果)
好,言歸正傳。
在說是怎么運行的之前,先看幾個概念。
執行上下文(Execution Context)執行上下文簡單來說就是一個執行環境。它有全局環境、函數環境和eval函數環境之分。它會在javascript引擎執行你的腳本的時候去創建。
執行棧(Execution Stack)執行棧也就是常說的調用棧,它是一種擁有LIFO(后進先出)的數據結構。它會存儲代碼運行時創建的執行上下文
微任務(micro task)與宏任務(macro task)javasript中的任務分為微任務和宏任務兩種,這兩種任務的執行時機是不同的,因此區分js中哪些是宏任務,哪些是微任務則十分重要。我們常見的宏任務有:script任務、setTimeout、ajax等,常見的微任務比較典型的是:Promise.resolve().then()、process.nextTick、MutationObserver等。
事件循環(event loop)js是單線程的,也就是說它一次僅能處理一個任務。但js所在的宿主環境,也就是我們所說的瀏覽器并不是單線程的(這里宿主環境僅討論瀏覽器)。它在遇到一些任務時,比如說setTimeout、event listener等。它會告訴瀏覽器:老兄幫個忙,事成后通知我一聲,小弟我先干別的事去了。瀏覽器會回應說:交給我吧,小老弟,事成后我放到任務隊列,自己去取啊。于是,js開始執行script任務,執行完了就開始檢查有沒有微任務啊,沒有的話就從任務隊列開始取宏任務執行,每執行完一次宏任務,就去看看有沒有微任務,有的話就執行完成,再執行宏任務,如此往復。如下:
了解了這幾個概念,再來看看javascript是怎么執行代碼的就比較輕松愉快了。開始吧
console.log(1) Promise.resolve().then(function () { console.log(2) }) new Promise(function(resolve, reject){ console.log(3) resolve() }).then(function () { console.log(4) setTimeout(function () { console.log(5) }) }) console.log(6) setTimeout(function () { Promise.resolve().then(function () { console.log(7) setTimeout(function () { console.log(8) }) }) })
js引擎在執行這段代碼的時候,首先將全局執行上下文壓入棧中:
然后呢,在執行的時候會碰到console.log函數,將它壓入棧中:
這個時候,直接執行console函數,并輸出1。然后console函數出棧:
繼續往下執行,碰到了Promise.resolve().then(),先將Promise.resolve().then()壓入棧中(這里,我為了圖方便就把它看成整體了,不然得畫很多圖)。
然后執行Promise.resolve().then(),前面說過,這個then()函數是個微任務,它會將傳入給它的回調函數加入到微任務隊列中。
然后Promise.resolve().then()就出棧了。
接著執行,遇到promise的構造函數,這個構造函數是一個宏任務,會直接將傳遞給它的函數壓入棧中。
執行console函數并輸出3,執行完,console函數出棧,接著執行resolve()函數,并出棧。
然后繼續執行then函數,將傳遞給then函數的參數函數放到微任務隊列中:
繼續來,繼續往下執行。碰到console.log(6),二話不說,直接壓入棧中,執行,輸出6,出棧,一氣呵成。
接著,引擎碰到了setTimeout函數,這家伙是個宏任務,但同時它會將傳遞給它的函數,加入到任務隊列中:
好了,到此第一波宏任務就全部執行完畢。接著,引擎就會去看一下微任務隊列中有沒有任務,如果有的話,執行它們。
現在看到的是,微任務隊列中有兩個任務。按照隊列的先入先出規則,先從function () {console.log(2)}開始執行。先是函數入棧,然后執行函數,輸出2,然后函數出棧。
接著執行下面這段代碼:
console.log(4) setTimeout(function () { console.log(5) })
先從console.log(4)開始,先將它入棧,然后執行它,輸出4,然后函數出棧。
接著執行:
setTimeout(function () { console.log(5) })
將
function () { console.log(5) }
加入到任務隊列中去
先執行:
function(){ Promise.resolve().then(function () { console.log(7) setTimeout(function () { console.log(8) }) }) }
這里執行這個函數的時候遇到一個微任務,將這個微任務添加到微任務隊列,如下:
這批次的宏任務就執行完畢了,接著就回去檢查微任務隊列中有沒有待執行的任務。一看還真有兩個小可愛等待執行,于是沒什么好說的,直接擰出去就執行
先是執行console.log(7),然后輸出7。接著執行setTimeout,將傳遞給他的任務添加到任務隊列中去:
最后就剩這兩個函數了,按照隊列的先入后出一次執行吧,輸出5和8。
好了,最后的結果就是1,3,6,2,4,7,5,8。你寫對了了嗎?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101033.html
摘要:關鍵字計算為當前執行上下文的屬性的值。毫無疑問它將指向了這個前置的對象。構造函數也是同理。嚴格模式無論調用位置,只取顯式給定的上下文綁定的,通過方法傳入的第一參數,否則是。其實并不屬于特殊規則,是由于各種事件監聽定義方式本身造成的。 this 是 JavaScript 中非常重要且使用最廣的一個關鍵字,它的值指向了一個對象的引用。這個引用的結果非常容易引起開發者的誤判,所以必須對這個關...
摘要:巧前端基礎進階全方位解讀前端掘金我們在學習的過程中,由于對一些概念理解得不是很清楚,但是又想要通過一些方式把它記下來,于是就很容易草率的給這些概念定下一些方便自己記憶的有偏差的結論。 計算機程序的思維邏輯 (83) - 并發總結 - 掘金從65節到82節,我們用了18篇文章討論并發,本節進行簡要總結。 多線程開發有兩個核心問題,一個是競爭,另一個是協作。競爭會出現線程安全問題,所以,本...
摘要:巧前端基礎進階全方位解讀前端掘金我們在學習的過程中,由于對一些概念理解得不是很清楚,但是又想要通過一些方式把它記下來,于是就很容易草率的給這些概念定下一些方便自己記憶的有偏差的結論。 計算機程序的思維邏輯 (83) - 并發總結 - 掘金從65節到82節,我們用了18篇文章討論并發,本節進行簡要總結。 多線程開發有兩個核心問題,一個是競爭,另一個是協作。競爭會出現線程安全問題,所以,本...
摘要:毫無疑問,設計模式于己于他人于系統都是多贏的設計模式使代碼編寫真正工程化設計模小書前端掘金這是一本關于的小書。 JavaScript 常見設計模式解析 - 掘金設計模式(Design pattern)是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。毫無疑問,設計模式于己于他人于系統都是多贏的;設計...
摘要:忍者級別的函數操作對于什么是匿名函數,這里就不做過多介紹了。我們需要知道的是,對于而言,匿名函數是一個很重要且具有邏輯性的特性。通常,匿名函數的使用情況是創建一個供以后使用的函數。 JS 中的遞歸 遞歸, 遞歸基礎, 斐波那契數列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執行機制 本文的目的就是要保證你徹底弄懂javascript的執行機制,如果...
閱讀 3129·2021-11-08 13:18
閱讀 2276·2019-08-30 15:55
閱讀 3602·2019-08-30 15:44
閱讀 3063·2019-08-30 13:07
閱讀 2774·2019-08-29 17:20
閱讀 1942·2019-08-29 13:03
閱讀 3403·2019-08-26 10:32
閱讀 3218·2019-08-26 10:15