摘要:本章會對語言引擎,運行時,調用棧做一個概述。調用棧只是一個單線程的編程語言,這意味著它只有一個調用棧。查看如下代碼當引擎開始執行這段代碼的時候,調用棧會被清空。之后,產生如下步驟調用棧中的每個入口被稱為堆棧結構。
原文請查閱這里,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。
本系列持續更新中,Github 地址請查閱這里。
這是 JavaScript 工作原理的第一章。本章會對語言引擎,運行時,調用棧做一個概述。
隨著 JavaScript 越來越流行,團隊也利用其在他們諸如前端,后端,混合 apps,嵌入設備以及更多設備等開發棧中的不同層面的支持。
本章系列的第一章,本系列旨在深入 JavaScript 并理解它是如何運行的:我們認為在了解 JavaScript 的構建模塊和它們是如何捏合在一起工作之后你將會寫出更好的代碼和 apps。我們將會分享一些當在創建 SessionStack 時候的經驗法則,SessionStack 是一個輕量級的 JavaScript 程序它擁有強壯性和高性能的優點以保持競爭力。
正如 GitHut stats 所顯示的那樣,JavaScript 的活躍庫和總推送數在 Github 排名第一。其它方面的表現也不會比其它語言落下太多。
(點擊查看最新 Github 語言統計)
如果工程非常依賴于 JavaScript,那么這意味著開發者不得不使用 JavaScript 和其語言生態提供的一切事物,為了能夠創造出很酷的軟件,就得更加深入地了解 JavaScript 語言的內部工作機制。
事實上,有很多開發者在每天日常開發中都會使用 JavaScript 但是卻不了解其底層的知識。
概述幾乎所有人都已經聽說過 V8 引擎的概念,并且很多人知道 JavaScript 是單線程的或者說是使用回調隊列的。
在本章中,我將會詳細地過一下這些概念并解釋 JavaScript 的工作原理。有賴于了解這些細節,通過合理地使用提供的 APIs 你將可能寫出更好的,非阻塞的程序。
如果你是新手,本文將會幫助你理解為什么和其它語言比較 JavaScript 是不可思議的。
如果你是一個經驗豐富的 JavaScript 開發者,但愿,它將會讓你更加深入地了解 JavaScript 運行時工作原理。
JavaScript 引擎谷歌 V8 引擎是流行的 JavaScript 引擎之一。V8 引擎在諸如 Chrome 和 Node.js 內部使用。這里有一個簡單的視圖來描繪其大概。
引擎包括兩個主要組件:
動態內存管理 - 在這里分配內存
調用棧-這里代碼執行即是你的堆棧結構
運行時幾乎每個 JavaScript 開發者都使用過一些瀏覽器 API(比如 setTimeout)。然而這些 API并不是引擎所提供的。
那么它們從何而來?
事實上這個情況有點復雜呃。。
所以,除了引擎但是實際上還有更多其它方面的東西。有被稱為 Web API 的東西,這些 Web API 是由瀏覽器提供的,比如 DOM,AJAX,setTimeout 以及其它。
于是乎,就有了流行的事件循環和回調隊列。
調用棧JavaScript 只是一個單線程的編程語言,這意味著它只有一個調用棧。這樣它只能一次做一件事情。
調用棧是一種數據結構,里面會記錄我們在程序中的大概位置。當執行進入一個函數,把它置于棧的頂部。如果從函數中返回則從棧頂部移除函數。這就是調用棧所能夠做的事情。
舉個栗子。查看如下代碼:
function multiply(x, y) { return x * y; } function printSquare(x) { var s = multiply(x, x); console.log(s); } printSquare(5);
當引擎開始執行這段代碼的時候,調用棧會被清空。之后,產生如下步驟:
調用棧中的每個入口被稱為堆棧結構。
當拋出異常的時候這正好是堆棧追蹤是如何被構造出來的-當發生異常的時候這基本上是調用棧的狀態。看下如下代碼:
function foo() { throw new Error("SessionStack will help you resolve crashes:)"); } function bar() { foo(); } function start() { bar(); } start();
如果在 Chrome 中執行(假設代碼在 foo.js 的文件中),將會產生如下的堆棧追蹤:
"堆棧溢出"-當你達到最大調用棧大小的時候發生。這種情況相當容易發生,特別是當你使用遞歸而沒有仔細地檢查代碼的時候。查看下如下代碼:
function foo() { foo(); } foo();
當引擎開始執行這段代碼的時候,它開始調用 foo 函數。這個函數,然而,會遞歸并開始調用其自身而沒有任何結束條件。所以在每步執行過程中,調用堆棧會反復地添加同樣的函數。執行過程如下所示:
在某一時刻,然而,調用堆棧中的函數調用次數超過了調用堆棧的實際大小,這樣瀏覽器決定拋出錯誤的動作,如下所示:
在單線程中運行代碼會相當輕松因為你不用處理多線程環境中產生的一些復雜情況,比如死鎖。
但是在單線程運行代碼也會有相當的限制。由于 JavaScript 只有一個調用棧,如果運行很慢會發生什么?
并發和事件循環當你在調用棧中有函數為了完成運行需要消耗大量的時間的時候會發生什么?例如,想象一下你想要在瀏覽器用 JavaScript 來執行一些復雜的圖像轉化。
你或許會問-為什么這也是個問題?問題是這樣的當調用棧有函數需要執行,瀏覽器實際上不能做其它任何事-它被阻塞了。這意味著瀏覽器不能夠執行渲染,它不能夠運行其它代碼,它卡住了。如果你想要在 app 中擁有酷炫的流暢 UI 體驗,這將會是個問題。
這不會是唯一的問題。一旦瀏覽器開始在調用棧中執行如此多的任務,瀏覽器將會在相當一段時間內停止交互。大多數瀏覽器會拋出一個錯誤,詢問你是否關閉網頁。
現在,這并不是最好的用戶體驗,難道不是嗎?
因此,如何不阻塞 UI 且不讓瀏覽器停止響應來執行運行緩慢的代碼呢?使用異步回調。
這將會在 『JavaScript 工作原理』 第二章:『在V8 引擎中如何寫最佳代碼的 5 條小技巧』中進行詳細闡述。
本系列持續更新中,Github 地址請查閱這里。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95125.html
摘要:本章會對語言引擎,運行時,調用棧做一個概述。調用棧只是一個單線程的編程語言,這意味著它只有一個調用棧。查看如下代碼當引擎開始執行這段代碼的時候,調用棧會被清空。之后,產生如下步驟調用棧中的每個入口被稱為堆棧結構。 原文請查閱這里,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。 本系列持續更新中,Github 地址請查閱這里。 這是 JavaScript 工作原...
摘要:文件系統請求和相關請求都會放進這個線程池處理其他的請求,如網絡平臺特性相關的請求會分發給相應的系統處理單元參見設計概覽。 譯者按:在 Medium 上看到這篇文章,行文脈絡清晰,闡述簡明利落,果斷點下翻譯按鈕。第一小節背景鋪陳略啰嗦,可以略過。剛開始我給這部分留了個 blah blah blah 直接翻后面的,翻完之后回頭看,考慮完整性才把第一節給補上。接下來的內容干貨滿滿,相信對 N...
摘要:調用棧是一種數據結構,它記錄了我們在程序中的位置。當從這個函數返回的時候,就會將這個函數從棧頂彈出,這就是調用棧做的事情。而且這不是唯一的問題,一旦你的瀏覽器開始處理調用棧中的眾多任務,它可能會停止響應相當長一段時間。 原文地址: https://blog.sessionstack.com... PS: 好久沒寫東西了,最近一直在準備寫一個自己的博客,最后一些技術方向已經敲定了,又可以...
摘要:本章將會深入谷歌引擎的內部結構。一個引擎可以用標準解釋程序或者即時編譯器來實現,即時編譯器即以某種形式把解釋為字節碼。引擎的由來引擎是由谷歌開源并以語言編寫。注意到沒有使用中間字節碼來表示,這樣就不需要解釋器了。 原文請查閱這里,略有刪減。 本系列持續更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第二章。 本章將會深入谷歌 V8 引擎的內部結構。我們也會...
摘要:理解執行上下文和執行堆棧對于理解的其它概念如提升,范圍和閉包至關重要。正確地理解執行上下文和執行堆棧將幫助你更好地使用開發應用。引擎執行位于執行堆棧頂部的方法。當調用時,為該函數創建一個新的執行上下文,并且把它推入到當前執行堆棧。 By Sukhjinder Arora | Aug 28, 2018 原文 如果你是或者你想要成為一名js開發者,那么你必須了解js程序內部的運作。理解執行...
閱讀 1948·2021-11-24 10:45
閱讀 1452·2021-11-18 13:15
閱讀 4524·2021-09-22 15:47
閱讀 3902·2021-09-09 11:36
閱讀 2006·2019-08-30 15:44
閱讀 3081·2019-08-29 13:05
閱讀 2495·2019-08-29 12:54
閱讀 1986·2019-08-26 13:47