引擎:負責整個js程序的編譯和執行過程
編譯器:負責語法分析和代碼生成
作用域:收集和維護一系列查詢(由所有聲明的標識符組成)
【例子:聲明一個變量并賦值 var a = value;】
Step1.編譯器對該程序段分解成詞法單元 "var" 、"a"、 "="、 "value"、";"
Step2.編譯器對以上的詞法單元解析成一個樹結構(抽象語法樹AST)
javascript的語法解析器Espsrima提供了一個在線解析的工具
在過程中,編譯器詢問作用域是否已經存在一個以"a"命名的變量在同一個作用域的集合中?若YES -> 編譯器忽略該聲明,繼續編譯;若NO -> 編譯器要求作用域在當前作用域的集合中聲明一個新變量,命名為a
Step3.編譯器生成處理 賦值操作“a = 2”的代碼
Step4.引擎運行step3生成的代碼時會詢問作用域,在當前作用域的集合中是否存在一個叫"a"的變量?若YES -> 引擎使用變量a ->Step5;若NO -> 引擎沿著作用域鏈繼續查找變量a ->Step6
Step5.引擎執行編譯器生成的代碼,把2賦值給變量a
Step6.引擎拋出一個異常
【總結】變量的賦值會經過兩個階段:
1.編譯器在作用域中聲明一個變量(若之前未聲明過)
2.運行時引擎在作用域中查找該變量
【擴展】
Step4中引擎查詢變量有兩種類型:LHS 和 RHS
LHS: 找到變量的容器本身
RHS:找到變量的值
例子:
function foo(a){var b = a;return a+b}
var c = foo(2);//在該例子中,LHS有:a = 2 、c= 、b=
//RHS有:=foo(2)、 =a、a+、+b