摘要:工作機(jī)制第部分本文轉(zhuǎn)載自眾成翻譯譯者網(wǎng)絡(luò)埋伏紀(jì)事鏈接原文隨著越來越受歡迎,開發(fā)團(tuán)隊正在將其用在技術(shù)棧的各個方面,包括前端后端混合應(yīng)用嵌入式設(shè)備等等。之后,步驟將是如下這樣調(diào)用棧中的每個條目稱為棧幀。
JavaScript工作機(jī)制:第1部分
本文轉(zhuǎn)載自:眾成翻譯
譯者:網(wǎng)絡(luò)埋伏紀(jì)事
鏈接:http://www.zcfy.cc/article/3965
原文:https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf
隨著JavaScript越來越受歡迎,開發(fā)團(tuán)隊正在將其用在技術(shù)棧的各個方面,包括 - 前端、后端、混合應(yīng)用、嵌入式設(shè)備等等。
如GitHut統(tǒng)計所示,JavaScript在GitHub中的活動存儲庫和總推送方面位于前列,在其他方面也不差。
(查看最新的GitHub語言統(tǒng)計信息)。
如果項目越來越依賴于JavaScript,這意味著開發(fā)人員必須更深入地了解內(nèi)部機(jī)制,才能利用語言和生態(tài)系統(tǒng)提供的所有技術(shù),構(gòu)建出驚艷的軟件。
事實證明,雖然有很多開發(fā)人員每天都在使用JavaScript,但并不知道它的工作機(jī)制。
概述幾乎所有人都已經(jīng)聽說過V8引擎的概念,大多數(shù)人都知道JavaScript是單線程的,或者是使用回調(diào)隊列。
在這篇文章中,我們將詳細(xì)介紹所有這些概念,并解釋JavaScript的工作機(jī)制。通過了解這些細(xì)節(jié),您將能夠正確利用提供的API,編寫更好的非阻塞應(yīng)用程序。
如果您是一個JavaScript新手,此博文將幫助您了解為什么JavaScript與其他語言相比是如此“怪異”。
而如果您是一位經(jīng)驗豐富的JavaScript開發(fā)人員,希望能夠提供與您每天使用的JavaScript運(yùn)行時有關(guān)的一些新鮮見解。
JavaScript引擎JavaScript引擎的一個流行示例是Google的V8引擎。例如,V8引擎在Chrome和Node.js中使用。如下是它看起來像什么的一個簡單視圖:
引擎由兩個主要組成部分組成:
內(nèi)存堆 - 這是內(nèi)存分配發(fā)生的地方
調(diào)用棧 - 這是您的代碼執(zhí)行所在的棧幀
運(yùn)行時瀏覽器中已經(jīng)有幾個幾乎所有JavaScript開發(fā)人員都會使用的API(比如 setTimeout)。不過,這些API不是由引擎提供的。
那么,它們是來自哪里呢?
事實證明,現(xiàn)實有點(diǎn)復(fù)雜。
所以,除了引擎以外,實際上還有更多東西。有一些由瀏覽器提供的,稱為Web API的東西,比如DOM、AJAX、setTimeout等等。還有超受歡迎的事件循環(huán)和回調(diào)隊列。
調(diào)用棧JavaScript是一種單線程編程語言,這意味著它只有一個調(diào)用棧。因此,它一次只能做一件事。
調(diào)用棧是一種數(shù)據(jù)結(jié)構(gòu),它基本上是記錄了我們處于程序中哪個地方。如果單步執(zhí)行進(jìn)一個函數(shù),就把該函數(shù)放在棧頂。如果從函數(shù)返回,就把它從棧頂彈出。這就是棧所做的事情。
下面我們來看一個示例。看看下面的代碼:
function multiply(x, y) { return x * y; } function printSquare(x) { var s = multiply(x, x); console.log(s); } printSquare(5);
引擎開始執(zhí)行這段代碼時,調(diào)用棧是空的。之后,步驟將是如下這樣:
調(diào)用棧中的每個條目稱為棧幀。
而這正是在異常被拋出時,棧跟蹤被構(gòu)造的方式 - 當(dāng)異常發(fā)生時,它基本上是調(diào)用棧的狀態(tài)。看看下面的代碼:
function foo() { throw new Error("SessionStack will help you resolve crashes :)"); } function bar() { foo(); } function start() { bar(); } start();
如果是在Chrome中執(zhí)行這段代碼(假設(shè)此代碼位于一個名為foo.js的文件中),則會產(chǎn)生以下棧跟蹤信息:
“爆棧” - 當(dāng)達(dá)到最大調(diào)用棧大小時,就會發(fā)生這種情況。并且這非常容易發(fā)生,特別是如果使用遞歸而不充分測試代碼時。請看如下示例代碼:
function foo() { foo(); } foo();
當(dāng)引擎開始執(zhí)行這段代碼時,它首先調(diào)用函數(shù)“foo”。不過,這個函數(shù)是遞歸的,并且開始調(diào)用自身而沒有任何終止條件。所以在執(zhí)行的每個步驟中,相同的函數(shù)都被一次又一次地添加到調(diào)用棧中??雌饋硐襁@樣:
然而,在某些時候,如果調(diào)用棧中的函數(shù)調(diào)用量超過了調(diào)用棧的實際大小,瀏覽器就會決定采取行動,拋出一個錯誤,看起來像這樣:
在單個線程上運(yùn)行代碼可能很容易,因為您不必處理在多線程環(huán)境中出現(xiàn)的復(fù)雜場景,例如死鎖。
但在單線程上運(yùn)行也有很大限制。由于JavaScript有一個調(diào)用棧,當(dāng)事情緩慢時會發(fā)生什么?
并發(fā)和事件循環(huán)當(dāng)在調(diào)用棧中有函數(shù)調(diào)用需要大量時間才能處理完時,會發(fā)生什么?例如,假設(shè)想在瀏覽器中使用JavaScript進(jìn)行一些復(fù)雜的圖像轉(zhuǎn)換。
你可能會問 - 這怎么就成了一個問題呢?原因是,在調(diào)用堆有函數(shù)要執(zhí)行的同時,瀏覽器實際上不能做任何事情 - 它被阻塞了。這意味著瀏覽器無法渲染,它不能運(yùn)行任何其他代碼,它只是卡住了。如果想在應(yīng)用中有流暢的UI,這會出問題。
而這不是唯一的問題。一旦瀏覽器開始處理調(diào)用棧中的許多任務(wù),它可能會停止響應(yīng)很長時間。大多數(shù)瀏覽器通過引發(fā)一個錯誤來采取行動,詢問您是否要終止網(wǎng)頁。
現(xiàn)在,這不是最好的用戶體驗,對吧?
那么,如何執(zhí)行繁重的代碼,而不阻塞UI并且不會使瀏覽器無響應(yīng)呢?好吧,解決方案是異步回調(diào)。
我將在教程的第2部分中詳細(xì)介紹。敬請關(guān)注 :)
歡迎關(guān)注我的公眾號,關(guān)注前端文章:
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/84847.html
摘要:忍者級別的函數(shù)操作對于什么是匿名函數(shù),這里就不做過多介紹了。我們需要知道的是,對于而言,匿名函數(shù)是一個很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...
摘要:從異步過程的角度看,函數(shù)就是異步過程的發(fā)起函數(shù),事件監(jiān)聽函數(shù)就是異步過程的回調(diào)函數(shù)。事件觸發(fā)時,表示異步任務(wù)完成,會將事件監(jiān)聽器函數(shù)封裝成一條消息放到消息隊列中,等待主線程執(zhí)行。 1.為什么JavaScript是單線程? JavaScript語言的一大特點(diǎn)就是單線程,也就是說,同一個時間只能做一件事。那么,為什么JavaScript不能有多個線程呢?這樣能提高效率啊。JavaScrip...
摘要:第一階段基礎(chǔ)階段基礎(chǔ)程序員重點(diǎn)把搞熟練核心是安裝配置基本操作目標(biāo)能夠完成基本的系統(tǒng)安裝,簡單配置維護(hù)能夠做基本的簡單系統(tǒng)的開發(fā)能夠在中型系統(tǒng)中支持某個功能模塊的開發(fā)。本項不做重點(diǎn)學(xué)習(xí),除非對前端有興趣。 第一階段:基礎(chǔ)階段(基礎(chǔ)PHP程序員) 重點(diǎn):把LNMP搞熟練(核心是安裝配置基本操作) 目標(biāo):能夠完成基本的LNMP系統(tǒng)安裝,簡單配置維護(hù);能夠做基本的簡單系統(tǒng)的PHP開發(fā);能夠在P...
摘要:心塞塞根據(jù)規(guī)范,事件循環(huán)是通過任務(wù)隊列的機(jī)制來進(jìn)行協(xié)調(diào)的。等便是任務(wù)源,而進(jìn)入任務(wù)隊列的是他們指定的具體執(zhí)行任務(wù)回調(diào)函數(shù)。然后當(dāng)前本輪的結(jié)束,主線程可以繼續(xù)取下一個執(zhí)行。 依然是:經(jīng)濟(jì)基礎(chǔ)決定上層建筑。 說明 首先,旨在搞清常用的同步異步執(zhí)行機(jī)制 其次,暫時不討論node.js的Event Loop執(zhí)行機(jī)制,以下關(guān)于瀏覽器的Event Loop執(zhí)行機(jī)制 最后,借鑒了很多前輩的研究文...
摘要:最近剛剛看完了你不知道的上卷,對有了更進(jìn)一步的了解。你不知道的上卷由兩部分組成,第一部分是作用域和閉包,第二部分是和對象原型。附錄詞法這一章并沒有說明機(jī)制,只是介紹了中的箭頭函數(shù)引入的行為詞法。第章混合對象類類理論類的機(jī)制類的繼承混入。 最近剛剛看完了《你不知道的 JavaScript》上卷,對 JavaScript 有了更進(jìn)一步的了解。 《你不知道的 JavaScript》上卷由兩部...
閱讀 3127·2021-08-03 14:05
閱讀 2169·2019-08-29 15:35
閱讀 704·2019-08-29 13:30
閱讀 3195·2019-08-29 13:20
閱讀 2561·2019-08-23 18:15
閱讀 1829·2019-08-23 14:57
閱讀 2244·2019-08-23 13:57
閱讀 1347·2019-08-23 12:10