原文鏈接 How JavaScript works: an overview of the engine, the runtime, and the call stack by Alexander Zlatkovjavascript
這個JavaScript 運行原理的第一章,一共18章,會後續持續更新,盡情期待,也能夠關注一下,防止迷路前端
因爲JavaScript愈來愈流行,各個團隊都在許多不一樣的技術棧中使用它—前端,後端,混合APPs,嵌入式設備等等。java
這篇文章是整個系列中的第一篇,旨在深刻探討Javascript和它的運行原理:咱們認爲,經過了解JavaScript的組成部分以及它們如何一塊兒發揮做用,你可以編寫出更好的代碼和應用。咱們還將分享在構建SessionStack(做者所在的公司)時使用的一些經驗法則,SessionStack是一種輕量級JavaScript應用程序,必須強大且高性能才能保持競爭力。git
如同GitHut stats展現的同樣,就活動資源倉庫和GitHub中的Push總數而言,JavaScript排名第一。在其餘類別中也沒有落後太多。web
若是項目愈來愈依賴JavaScript,則意味着開發人員必須利用語言和生態系統提供的全部內容,並對內部進行愈來愈深刻的瞭解,才能構建出色的軟件。chrome
可是事實證實,有不少開發人員天天都在使用JavaScript,但並不瞭解其內部原理。編程
幾乎每一個人都已經據說過V8引擎,並且大多數人都知道JavaScript是單線程的,或者它正在使用回調隊列。後端
在本文中,咱們將詳細介紹全部這些概念,並解釋JavaScript實際如何運行。經過了解這些詳細信息,可以編寫更好地,無阻塞的應用程序,這些應用程序能夠正確利用提供的API。瀏覽器
若是你是JavaScript的新手,此博客文章將幫助您瞭解JavaScript與其餘語言相比爲什麼如此「古怪」。安全
若是你是一位經驗豐富的JavaScript開發人員,但願它會爲你提供你天天使用的JavaScript運行時實際工做方式的新看法。
一個流行的JavaScript引擎是Google的V8,V8被用於chrome和Node.js中。舉個例子,下圖是V8的一個簡單視圖:
瀏覽器中有許多API幾乎全部的JavaScript開發人員都會用到(例如:"setTimeout")。這些API都不是JavaScript引擎提供的。
所以,他們從哪裏來的?
事實證實,現實狀況有點複雜。
固然,咱們還有很是流行的事件循環(event loop)和回調隊列(callback queue)。
Javascript 是單線程的編程語言,也就意味着它只有一個調用棧。由於在同一時間咱們只能作同一件事情。
調用棧是一種數據結構,它記錄了咱們在程序中的位置。如何進入了一個函數,咱們就將這個函數從頂部放入棧中,若是從函數返回,咱們就將該函數從棧頂移出棧。這就是調用棧所作的事情。
舉個例子,看如下代碼
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}
printSquare(5);
複製代碼
當引擎開始執行這段代碼的時候調用棧是空的。在此以後,每一步以下圖所示:
咱們也能夠明確的知道拋出異常時棧路徑(stack traces)是如何構造的—基本上就是異常發生時棧的狀態,看下面的代碼:
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轉換某些複雜的圖片。
你也許會問,爲何這是一個問題?這個問題關鍵在於當調用棧在執行的時候,瀏覽器不能執行其的任務—它被阻塞了。這也意味着瀏覽器不能渲染,不能運行其餘任務代碼,它就被卡在那。若是你但願的是一個流程的web應用,這將是一個問題。
這還不是惟一的問題。一旦瀏覽器開始處理「調用堆棧」中的許多任務,它可能會在至關長的時間內中止響應。並且大多數瀏覽器採起的方案都是拋出錯誤,詢問您是否要終止網頁。
所以咱們如何執行耗時的代碼而不去阻塞UI和致使瀏覽器不響應?方案是異步回調。
這個會在「JavaScript 運行原理」系列的第二章「深刻了解V8引擎 & 如何寫出最優代碼的5個提示」中進行講解。