Javascript 已成為了 Web 開發的必備技能,不僅限於瀏覽器端,也廣泛應用於 Node.js 、行動端、桌面端以及嵌入式裝置等多種應用場景。在 Javascript 執行的過程中,有一個很重要的概念,就是編譯過程。這篇文章將從編譯過程的角度介紹 Javascript 的執行過程。
編譯過程是將原始碼轉換成可執行程式碼的過程。在 Javascript 中,編譯過程可以分為兩個階段:解析階段和執行階段。
解析階段又分為兩個部分:詞法分析與文法分析。
詞法分析的任務是將原始碼分解成詞法單元(token),也就是語言中的最小單元。詞法單元包括關鍵字(如 function 、var )、標識符(如變數名和函數名)和操作符(如 、-、* 、/ 等)等。
例如,下面是一個簡單的函數宣告:
function add(x, y) { return x + y; }
這個函數宣告會被分解成以下的詞法單元:
Keyword 'function' Identifier 'add' Punctuator '(' Identifier 'x' Punctuator ',' Identifier 'y' Punctuator ')' Punctuator '{' Keyword 'return' Identifier 'x' Punctuator '+' Identifier 'y' Punctuator ';' Punctuator '}'
語法分析的任務是將詞法單元轉換成抽象語法樹(AST)。抽象語法樹是一種以樹狀結構表示程式碼語法結構的資料結構。每個節點代表了語法結構中的一個構造,子節點代表該構造的子構造。
例如,對於上面的函數聲明,產生的抽象語法樹如下所示:
{ "type": "FunctionDeclaration", "id": { "type": "Identifier", "name": "add" }, "params": [ { "type": "Identifier", "name": "x" }, { "type": "Identifier", "name": "y" } ], "body": { "type": "BlockStatement", "body": [ { "type": "ReturnStatement", "argument": { "type": "BinaryExpression", "operator": "+", "left": { "type": "Identifier", "name": "x" }, "right": { "type": "Identifier", "name": "y" } } } ] } }
解析階段完成後,Javascript 程式進入執行階段。執行階段的任務是執行抽象語法樹。
執行抽象語法樹的過程可以分成兩個階段:預編譯和執行。
預編譯的任務是處理變數和函數宣告。在執行階段開始前,Javascript 引擎會掃描程式的抽象語法樹,在目前的作用域內建立對應的變數和函數,這個過程稱為作用域的預處理。
首先,將所有的函數宣告提前,這個過程叫做函數宣告提升(Function Declarations Hoisting)。函數宣告提升的本質是將函數名稱和函數體提升到了目前作用域的頂端,因此可以在函數宣告之前呼叫函數。
例如,下面的程式碼:
add(1, 2); function add(x, y) { return x + y; }
等價於:
function add(x, y) { return x + y; } add(1, 2);
其次,將所有的變數宣告提前,這個過程叫變數提升(Variable Hoisting)。需要注意的是,變數提升只會提升變數的聲明,而不會提升變數的賦值語句。
例如,下面的程式碼:
console.log(a); var a = 1;
等價於:
var a; console.log(a); a = 1;
#執行程序依照語句出現的順序執行。在執行的過程中,變數會被賦值、函數會被呼叫、並且可能會被程式碼區塊或函數的作用域限制。
Javascript 的編譯過程包括解析階段和執行階段。解析階段包括詞法分析和語法分析,執行階段包括預編譯和執行。在執行階段之前,Javascript 引擎會預處理作用域,進行函數宣告提升和變數提升,然後依照語句出現的順序執行程式碼。
以上是javascript 編譯過程的詳細內容。更多資訊請關注PHP中文網其他相關文章!