摘要:編譯原理在傳統編譯語言的流程中,程序中的一段源代碼在執行之前會經歷三個步驟,統稱為編譯。定義聲明是在編譯階段進行的,而賦值是在執行階段進行的。
編譯原理
在傳統編譯語言的流程中,程序中的一段源代碼在執行之前會經歷三個步驟,統稱為“編譯”。
詞法分析
將由字符組成的字符串分解成(對編程語言來說)有意義的代碼塊,這些代碼塊被稱為詞法單元(token)。
語法分析
這個過程是將詞法單元流(數組)轉換成一個代表了程序語法結構的樹。這個樹被稱為“抽象語法樹”(AST)。
代碼生成
將 AST 轉換為可執行代碼的過程被稱為代碼生成。AST 轉化為一組機器指令。
JavaScript 引擎要復雜得多。例如,在語法分析和代碼生成階段有特定的步驟來對運行性能進行優化,包括對冗余元素進行優化等。
與其他語言不同,JavaScript 的編譯過程不是發生在構建之前的。對于 JavaScript 來說,大部分情況下編譯發生在代碼執行前的幾微秒(甚至更短)的時間內。
引擎:
從頭到尾負責整個 JavaScript 程序的編譯及執行過程。
編譯器:
負責語法分析及代碼生成等臟活累活。
作用域:
負責收集并維護由所有聲明的標識符(變量)組成的一系列查詢,并實施一套非常嚴格的規則,確定當前執行的代碼對這些標識符的訪問權限。
編譯器可以控制作用域、而引擎更多的是查詢(有可能會拋出異常)。
引擎在查詢作用域的時候,有兩種查詢方法:
LHS:當變量出現在賦值操作的左側時,試圖找到變量的位置。如果在頂層(全局作用域)中也無法找到目標變量,全局作用域中就會創建一個具有該名稱的變量。
RHS:當變量出現在賦值操作的右側時,簡單地查詢值。在所有嵌套的作用域中遍尋不到所需的變量,引擎就會拋出 ReferenceError 異常。
作用域有兩種主要的工作模型:詞法作用域(靜態)、動態作用域;
詞法作用域是在編譯器詞法分析的時候生成的。
eval和with會動態改變詞法作用域,這樣會影響js引擎編譯階段的優化工作,會慢。所以嚴格模式禁用
聲明提升js的代碼在生成前,會先對代碼進行預編譯,編譯的一部分工作就是找到所有的聲明,然后建立作用域將其關聯起來,因此,在當前作用域內包括變量和函數在內的所有聲明都會在任何代碼被執行前首先被處理。
定義聲明是在編譯階段進行的,而賦值是在執行階段進行的。
** var 與 let區別
編譯過程中用var定義的變量,會默認分配undefined值;
用let定義的變量,不會有任何值分配,所以在let之前使用這個變量會報錯。
提升的優先級:
函數提升的優先級比變量高(函數聲明會提升到變量聲明之前,變量聲明一定會被忽略)
對于同名的變量聲明,Javascript采用的是忽略原則,后聲明的會被忽略
對于同名的函數聲明,Javascript采用的是覆蓋原則,先聲明的會被覆蓋
示例1:
console.log(c) // ReferenceError b = function c() {};
等號右邊的是不會變量提升的喲,可以見得編譯過程中沒有管等號右邊。
示例2:
b = function c() {}; console.log(c) // ReferenceError
執行過程中創建了c變量,但是只能在函數c中使用
示例3:
b = function c() { c = 3; }; b(); console.log(c); // ReferenceError
等價于
b = function() { let c = 3; c = 4 // 沒有賦值到window上喲 }; b(); console.log(c); // ReferenceError
示例4
(function () { try { throw new Error(); } catch (x) { var x = 1, y = 2; // 注意這里的x被覆蓋 console.log(x); } console.log(x); console.log(y); })(); // 1 undefiend 2
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105771.html
摘要:無論你使用的是解釋型語言還是編譯型語言,都有一個共同的部分將源代碼作為純文本解析為抽象語法樹的數據結構。和抽象語法樹相對的是具體語法樹,通常稱作分析樹。這是引入字節碼緩存的原因。 這是專門探索 JavaScript 及其所構建的組件的系列文章的第 14 篇。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 如果你錯過了前面的章節,可以在這里找到它們: JavaS...
摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...
摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...
摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內部,也就是說為其聲明的變量隱式的劫持了所在的塊級作用域。 作用域與閉包 如何用js創建10個button標簽,點擊每個按鈕時打印按鈕對應的序號? 看到上述問題,如果你能看出來這個問題實質上是考對作用域的理解,那么恭喜你,這篇文章你可以不用看了,說明你對作用域已經理解的很透徹了,但是如果你看不出來這是一道考作用域的題目,...
閱讀 3398·2023-04-25 22:04
閱讀 2197·2021-11-22 15:29
閱讀 2161·2021-10-11 10:57
閱讀 1402·2021-09-24 09:48
閱讀 3147·2021-09-09 09:34
閱讀 2543·2021-09-02 15:21
閱讀 2393·2019-08-30 15:53
閱讀 1120·2019-08-30 14:07