如何理解單線程的JavaScript及其工作原理
點擊上方 前端瓶子君,關(guān)注公眾號
回復(fù)算法,加入前端編程面試算法每日一題群
隨著JavaScript的日益流行,團隊也利用其在前端,后端,混合APPS,嵌入式設(shè)備以及更多設(shè)備等開發(fā)棧中諸多層面的支持,JavaScript能創(chuàng)造出令人驚嘆的軟件,開發(fā)就必須更加深入了解JavaScript語言的內(nèi)部工作機制!
此篇文章會詳細地研究并解釋JavaScript的工作原理,通過了解這些細節(jié),通過合理地使用提供的APIs,你將能夠?qū)懗龈玫模亲枞某绦颉?/p>
一、單線程的來源
幾乎所有人都已經(jīng)聽過V8引擎的概念,并且很多人知道JavaScript是單線程的,JavaScript作為瀏覽器腳本語言,它的主要用途是與用戶交互,那么為什么JavaScript是單線程呢?如果JavaScript是多線程,當(dāng)頁面更新內(nèi)容的時候、用戶又觸發(fā)了交互,這時候線程間的同步問題會變得很復(fù)雜,為了避免復(fù)雜性,故JavaScript被設(shè)計成單線程。
二、JavaScript引擎
谷歌V8引擎是一個流行的JavaScript引擎。這里有一個簡單的視圖來描繪其大概模樣。
引擎包括兩個組件:
-
內(nèi)存堆——進行內(nèi)存分配的區(qū)域 -
調(diào)用棧——代碼執(zhí)行時棧中的位置
三、運行時
幾乎每個JavaScript開發(fā)者都使用過一些瀏覽器 API(比如setTimeout)。然而這些API并不是引擎所提供的。這些Web API是瀏覽器提供的,還有DOM事件,AJAX及其它。它們怎么執(zhí)行呢,實際情況有點復(fù)雜。
于是乎,就有了如此流行的事件循環(huán)(也稱event loop或事件輪詢)和回調(diào)隊列。
四、調(diào)用棧
前面我們說過,JavaScript是單線程的編程語言,這意味著只有一個調(diào)用棧。這樣它只能一次做一件事情。調(diào)用棧是一種數(shù)據(jù)結(jié)構(gòu)。當(dāng)執(zhí)行進入一個函數(shù),把它置于棧的底部。如果從函數(shù)中返回則從棧底部移除函數(shù)。這就是調(diào)用棧所做的事情。
舉個??子,看如下代碼:
fucntion multiply(x,y) {
return x * y;
}
function printSquare(x) {
var s = mulitiply(x,x);
console.log(s);
}
printSquare(s);
復(fù)制代碼
當(dāng)引擎開始執(zhí)行這段代碼的時候,調(diào)用棧會被清空,之后產(chǎn)生如下步驟:
五、堆棧溢出
一旦達到最大調(diào)用棧大小的時候發(fā)生。這種情況相當(dāng)容易發(fā)生。特別是當(dāng)你使用遞歸時,看下面的代碼:
function foo () {
foo();
}
foo();
復(fù)制代碼
當(dāng)引擎開始執(zhí)行這段代碼的時候,它開始調(diào)用foo函數(shù)。這個函數(shù),然而會遞歸并開始調(diào)用其自身而沒有任何結(jié)束條件。所以在每步執(zhí)行過程中,調(diào)用堆棧會反復(fù)添加foo函數(shù)。就會出現(xiàn)如下情況:
當(dāng)調(diào)用棧中的函數(shù)調(diào)用次數(shù)超過了調(diào)用棧的實際大小,瀏覽器決定拋出一個錯誤,如下圖所示:
小伙伴們可以自己在瀏覽器的控制臺里試試!
六、事件循環(huán)(Event Loop)
又該拿出那張經(jīng)典的圖了~
Event Loop 負(fù)責(zé)執(zhí)行代碼、收集和處理事件以及執(zhí)行隊列中的子任務(wù)。
具體包括:
-
Javascript 有一個主線程和執(zhí)行棧,所有的任務(wù)都會被放到調(diào)用棧等待主線程執(zhí)行 -
同步任務(wù)會被放在調(diào)用棧中,按照順序等待主線程依次執(zhí)行 -
主線程之外存在一個任務(wù)隊列,所有任務(wù)在主線程中以執(zhí)行棧的方式運行 -
同步任務(wù)都在主線程上執(zhí)行,棧中代碼在執(zhí)行的時候會調(diào)用 Web API,此時會產(chǎn)生一些異步任務(wù) -
異步任務(wù)會在有了結(jié)果(比如被監(jiān)聽的事件發(fā)生時)后,將注冊的回調(diào)函數(shù)放入任務(wù)隊列中 -
執(zhí)行棧中任務(wù)執(zhí)行完畢后,此時主線程處于空閑狀態(tài),會從任務(wù)隊列中獲取任務(wù)進行處理
以上過程會不斷重復(fù),這就是瀏覽器的運行機制,也是Event Loop。
最后
Event Loop 我們還得繼續(xù),理解它是突破前端第一層天花板的畢竟之路!
關(guān)于本文
來源:_啊嗚
https://juejin.cn/post/6991241111167565860
