摘要:調用棧是一種單線程編程語言,這意味著它只有一個調用堆棧。調用棧是一種數據結構,它記錄了我們在程序中的位置。而且這不是唯一的問題,一旦你的瀏覽器開始處理調用棧中的眾多任務,它可能會停止響應相當長一段時間。
本文是旨在深入研究JavaScript及其實際工作原理的系列文章中的第一篇:我們認為通過了解JavaScript的構建塊以及它們是如何工作的,將能夠編寫更好的代碼和應用程序。我們還將分享構建 SeStHealsStad 時使用的一些經驗法則,這是一個輕量級的 JavaScript 應用程序,必須保持健壯和高性能以保持競爭力。
想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你!
如 GitHut 統計 數據所示,在GitHub中的活動存儲庫和總推送方面,JavaScript處于頂部。它也不落后于其他類別。
如果項目越來越依賴于 JavaScript,這意味著開發人員必須利用語言和生態系統提供的所有內容,對內部進行更深入的了解,以便構建出色的軟件。
事實證明,有很多開發人員每天都在使用JavaScript,但卻不知道背后發生了什么。
概述幾乎每個人都已經聽說過 V8 引擎,大多數人都知道 JavaScript 是單線程的,或者它使用的是回調隊列。
在本文中,我們將詳細介紹這些概念,并解釋 JavaScrip 實際如何運行。通過了解這些細節,你將能夠適當地利用所提供的 API 來編寫更好的、非阻塞的應用程序。
如果您對JavaScript還比較陌生,那么本文將幫助您理解為什么JavaScript與其他語言相比如此“怪異”。
如果你是一個有經驗的JavaScript開發人員,希望它能讓您對每天使用的JavaScript運行時的實際工作方式有一些新的見解。
JavaScript引擎JavaScript引擎的一個流行示例是Google的V8引擎。例如,在Chrome和Node.js中使用V8引擎,下面是一個非常簡化的視圖:
V8引擎由兩個主要部件組成:
emory Heap(內存堆)?—?內存分配地址的地方
Call Stack(調用堆棧) — 代碼執行的地方
Runtime(運行時)有些瀏覽器的 API 經常被使用到(比如說:setTimeout),但是,這些 API 卻不是引擎提供的。那么,他們是從哪兒來的呢?事實上這里面實際情況有點復雜。
所以說我們還有很多引擎之外的 API,我們把這些稱為瀏覽器提供 API 稱為 Web API,比如說 DOM、AJAX、setTimeout等等。
然后我們還擁有如此流行的事件循環和回調隊列。
調用棧JavaScript是一種單線程編程語言,這意味著它只有一個調用堆棧。因此,它一次只能做一件事。
調用棧是一種數據結構,它記錄了我們在程序中的位置。如果我們運行到一個函數,它就會將其放置到棧頂,當從這個函數返回的時候,就會將這個函數從棧頂彈出,這就是調用棧做的事情。
來個栗子:
當程序開始執行的時候,調用棧是空的,然后,步驟如下:
每一個進入調用棧的都稱為調用幀。
這能清楚的知道當異常發生的時候堆棧追蹤是怎么被構造的,堆棧的狀態是如何的,讓我們看一下下面的代碼:
如果這發生在 Chrome 里(假設這段代碼實在一個名為 foo.js 的文件中),那么將會生成以下的堆棧追蹤:
"堆棧溢出",當你達到調用棧最大的大小的時候就會發生這種情況,而且這相當容易發生,特別是在你寫遞歸的時候卻沒有全方位的測試它。我們來看看下面的代碼:
當引擎開始執行這段代碼時,它首先調用函數“foo”。然而,這個函數是遞歸的,并且在沒有任何終止條件的情況下開始調用自己。因此,在執行的每一步中,相同的函數都會被一次又一次地添加到調用堆棧中,如下所示:
然而,在某些時候,調用堆棧中的函數調用數量超過了調用堆棧的實際大小,瀏覽器決定采取行動,拋出一個錯誤,它可能是這樣的:
在單個線程上運行代碼很容易,因為你不必處理在多線程環境中出現的復雜場景——例如死鎖。
但是在一個線程上運行也非常有限制,由于 JavaScript 只有一個調用堆棧,當某段代碼運行變慢時會發生什么?
當調用堆棧中的函數調用需要花費大量時間來處理時會發生什么情況? 例如,假設你希望在瀏覽器中使用JavaScript進行一些復雜的圖像轉換。
你可能會問-為什么這是一個問題?問題是,當調用堆棧有函數要執行時,瀏覽器實際上不能做任何其他事情——它被阻塞了,這意味著瀏覽器不能呈現,它不能運行任何其他代碼,它只是卡住了,如果你想在應用中使用流暢的頁面效果,這就會產生問題。
而且這不是唯一的問題,一旦你的瀏覽器開始處理調用棧中的眾多任務,它可能會停止響應相當長一段時間。大多數瀏覽器都會這么做,報一個錯誤,詢問你是否想終止 web 頁面。
這并不是最好的用戶體驗,不是嗎?
那么,我們怎樣才能在不阻塞UI和不使瀏覽器失去響應的情況下執行大量代碼呢?解決方案是異步回調。
這個在下一篇說明,我盡快把原作者的內容整理好!
代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行log 調試,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
原文:https://blog.sessionstack.com...
你的點贊是我持續分享好東西的動力,歡迎點贊!
交流干貨系列文章匯總如下,覺得不錯點個Star,歡迎 加群 互相學習。
https://github.com/qq44924588...
我是小智,公眾號「大遷世界」作者,對前端技術保持學習愛好者。我會經常分享自己所學所看的干貨,在進階的路上,共勉!
關注公眾號,后臺回復福利,即可看到福利,你懂的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99968.html
摘要:如果我們進入一個函數,我們在堆棧的頂部??纯聪旅娴拇a當引擎開始執行此代碼時,調用堆棧將為空。之后,步驟如下調用堆棧中的每個條目稱為堆棧幀。這正是拋出異常時構造堆棧跟蹤的方式當異常發生時,它基本上是調用堆棧的狀態。 隨著JavaScript越來越受歡迎,團隊正在利用這個技術棧在多個層次- 前端,后端,混合應用程序,嵌入式設備等等提供支持。 這篇文章旨在成為系列中第一個旨在深入挖掘Jav...
摘要:為了方便大家共同學習,整理了之前博客系列的文章,目前已整理是如何工作這個系列,可以請猛戳博客查看。以下列出該系列目錄,歡迎點個星星,我將更友動力整理理優質的文章,一起學習。 為了方便大家共同學習,整理了之前博客系列的文章,目前已整理 JavaScript 是如何工作這個系列,可以請猛戳GitHub博客查看。 以下列出該系列目錄,歡迎點個星星,我將更友動力整理理優質的文章,一起學習。 J...
摘要:調用堆棧是存放原始數據類型的地方除了函數調用之外。上一節中聲明變量后調用堆棧的粗略表示如下。解釋改變的正確方法是更改內存地址。在聲明時,將在調用堆棧上分配內存地址,該值是在堆上分配的內存地址。 這是專門探索 JavaScript 及其所構建的組件的系列文章的第 21 篇。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 如果你錯過了前面的章節,可以在這里找到它們:...
摘要:無論你使用的是解釋型語言還是編譯型語言,都有一個共同的部分將源代碼作為純文本解析為抽象語法樹的數據結構。和抽象語法樹相對的是具體語法樹,通常稱作分析樹。這是引入字節碼緩存的原因。 這是專門探索 JavaScript 及其所構建的組件的系列文章的第 14 篇。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 如果你錯過了前面的章節,可以在這里找到它們: JavaS...
摘要:調用棧是一種數據結構,它記錄了我們在程序中的位置。當從這個函數返回的時候,就會將這個函數從棧頂彈出,這就是調用棧做的事情。而且這不是唯一的問題,一旦你的瀏覽器開始處理調用棧中的眾多任務,它可能會停止響應相當長一段時間。 原文地址: https://blog.sessionstack.com... PS: 好久沒寫東西了,最近一直在準備寫一個自己的博客,最后一些技術方向已經敲定了,又可以...
閱讀 3157·2021-11-22 14:45
閱讀 3306·2019-08-29 13:11
閱讀 2309·2019-08-29 12:31
閱讀 927·2019-08-29 11:21
閱讀 2995·2019-08-29 11:09
閱讀 3624·2019-08-28 18:11
閱讀 1424·2019-08-26 13:58
閱讀 1279·2019-08-26 13:27