摘要:調(diào)用棧是一種單線程編程語言,這意味著它只有一個調(diào)用棧。這就是調(diào)用棧的功能。簡單代碼示例當引擎執(zhí)行這段代碼時,調(diào)用棧為空,之后運行如下每個叫做堆棧幀。調(diào)用棧就是通過堆棧幀來追蹤異常,堆棧幀基本就是調(diào)用棧出現(xiàn)異常時候的狀態(tài)。
概述
幾乎每個人都已經(jīng)聽說過V8引擎這個概念,而且大多人都知道JavaScript是單線程的,并且使用回調(diào)隊列。
這篇文章中,我們將詳細介紹這些概念,并解釋JavaScript實際運行的原理。通過了解這些詳細信息,將能夠編寫更好的非阻塞應用程序,以正確利用所提供的API。
JavaScript引擎最流行的JavaScript引擎莫過于Google的V8引擎,V8使用C++開發(fā),Chrome瀏覽器和Node.js都是基于V8引擎的,簡略的示意圖:
V8引擎包含兩個主要組件:
內(nèi)存堆(Memory Heap):負責內(nèi)存分配
調(diào)用棧(Call Stack):代碼執(zhí)行時,維護堆棧幀(Stack Frames)
幾乎所有的JavaScript開發(fā)者都使用過setTimeout這樣的API,然而這些APIs不是由V8引擎提供的。那這些APIs是哪來的呢?
盡管我們已經(jīng)有了V8引擎,但實際上我們還需要更多的接口或功能。我們把那些由瀏覽器提供的接口稱為Web APIs,比如DOM,AJAX,setTimeout等等。
接下來是事件循環(huán)(event lool)和回調(diào)隊列(callback queue)。
調(diào)用棧(Call Stack)JavaScript是一種單線程編程語言,這意味著它只有一個調(diào)用棧。因此,在同一時間它只能做一件事。
調(diào)用棧是一個數(shù)據(jù)結構,它會記錄代碼執(zhí)行的位置。例如我們執(zhí)行進入一個函數(shù),我們會把這個函數(shù)放在堆棧的頂部,函數(shù)執(zhí)行結束返回之后,我們把這個函數(shù)從堆棧中移除。這就是調(diào)用棧的功能。
簡單代碼示例:
function multiply(x, y) { return x * y; } function printSquare(x) { var s = nultiply(x, x); console.log(s); } printSquare(5);
當引擎執(zhí)行這段代碼時,調(diào)用棧為空,之后運行如下:
每個Step叫做堆棧幀(Stack Frame)。
調(diào)用棧就是通過堆棧幀來追蹤異常,堆棧幀基本就是調(diào)用棧出現(xiàn)異常時候的狀態(tài)。示例代碼如下:
function foo() { throw new Error("SessionStack will help you resolve crashes :)"); } function bar() { foo(); } function start() { bar(); }
假設上面代碼保存在foo.js文件,執(zhí)行上面代碼在Chrome瀏覽器中,Error的堆棧信息會如下圖打印出來:
單線程執(zhí)行代碼是無法充分利用CPU資源,使得運行效率低。由于JavaScript只有一個調(diào)用棧,如果運行效率變低,那應該怎么解決呢?
并發(fā)和事件循環(huán)想像一下如果調(diào)用棧里面有些函數(shù)的執(zhí)行需要大量的時間,例如在瀏覽器中進行復雜的圖片轉(zhuǎn)化,情況會怎么樣,為什么會有問題?
問題就是調(diào)用棧中的函數(shù)在執(zhí)行的過程中,瀏覽器是不能做其它事情的,也就是會被調(diào)用棧中的函數(shù)阻塞,此時瀏覽器不能渲染和運行其它代碼,完全被卡住了。這樣就很難實現(xiàn)流暢的UIs體驗。
而且另外一個問題也會由此發(fā)生,如果瀏覽器在調(diào)用棧中執(zhí)行很多這樣復雜且耗時的函數(shù)時,瀏覽器也會失去響應,出現(xiàn)假死狀態(tài)。
這絕對不是我們要的用戶體驗。
怎么才能執(zhí)行復雜且耗時的代碼,并且不會阻塞UI的渲染和導致瀏覽器假死呢?解決方案就是異步調(diào)用。異步調(diào)用會在第二篇系列文章(V8引擎和5招優(yōu)化)中解釋。
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94596.html
摘要:本章會對語言引擎,運行時,調(diào)用棧做一個概述。調(diào)用棧只是一個單線程的編程語言,這意味著它只有一個調(diào)用棧。查看如下代碼當引擎開始執(zhí)行這段代碼的時候,調(diào)用棧會被清空。之后,產(chǎn)生如下步驟調(diào)用棧中的每個入口被稱為堆棧結構。 原文請查閱這里,本文采用知識共享署名 4.0 國際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原...
摘要:本章會對語言引擎,運行時,調(diào)用棧做一個概述。調(diào)用棧只是一個單線程的編程語言,這意味著它只有一個調(diào)用棧。查看如下代碼當引擎開始執(zhí)行這段代碼的時候,調(diào)用棧會被清空。之后,產(chǎn)生如下步驟調(diào)用棧中的每個入口被稱為堆棧結構。 原文請查閱這里,本文采用知識共享署名 4.0 國際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原...
摘要:調(diào)用棧是一種單線程編程語言,這意味著它只有一個調(diào)用堆棧。調(diào)用棧是一種數(shù)據(jù)結構,它記錄了我們在程序中的位置。而且這不是唯一的問題,一旦你的瀏覽器開始處理調(diào)用棧中的眾多任務,它可能會停止響應相當長一段時間。 本文是旨在深入研究JavaScript及其實際工作原理的系列文章中的第一篇:我們認為通過了解JavaScript的構建塊以及它們是如何工作的,將能夠編寫更好的代碼和應用程序。我們還將分...
摘要:什么是中的調(diào)用棧調(diào)用棧就像是程序當前執(zhí)行的日志。當函數(shù)執(zhí)行結束時,將從調(diào)用棧中出去。了解全局和局部執(zhí)行上下文是掌握作用域和閉包的關鍵??偨Y引擎創(chuàng)建執(zhí)行上下文,全局存儲器和調(diào)用棧。 原文作者:Valentino 原文鏈接:https://www.valentinog.com/blog/js-execution-context-call-stack 什么是Javascript中的執(zhí)行上下文...
摘要:最受歡迎的引擎是,由和使用,用于,以及使用的。引擎它們是如何工作的全局執(zhí)行上下文和調(diào)用堆棧剛剛了解了引擎如何讀取變量和函數(shù)聲明,它們最終被放入了全局內(nèi)存堆中。事件循環(huán)只有一個任務它檢查調(diào)用堆棧是否為空。 為了保證可讀性,本文采用意譯而非直譯。 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 有沒有想過瀏覽器如何讀取和運行JS代碼? 這看起來很神奇,我們可以通過瀏覽...
閱讀 2448·2021-11-12 10:34
閱讀 1500·2019-08-29 16:15
閱讀 2707·2019-08-29 15:17
閱讀 1386·2019-08-23 17:09
閱讀 414·2019-08-23 11:37
閱讀 2478·2019-08-23 10:39
閱讀 516·2019-08-22 16:43
閱讀 3140·2019-08-22 14:53