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