Source code
Source code,即 ECMAScript 代碼,由任意 Unicode code point(即碼點,也稱碼位,上一篇筆記有)組成。詞法分析時,ECMAScript 代碼被轉(zhuǎn)換成一系列的 input elements,這些 elements 可以分為 white space、line terminator、comment、token 幾類。其中 Unicode 里的一些特定的碼位被當(dāng)做 white space 和 line terminator。comment 結(jié)尾的 line terminator 不被視作 comment 的內(nèi)容,而是一個單獨的 input element。
Token
token 可以分為如下幾類:
- identifier name
- reversed word
- keyword
- future reversed word
- null literal
- boolean literal
- identifier
- reversed word
- punctuator
- numeric literal
- string literal
- template(即字符串模板)
Lexical Environment
Lexical Environment 是一種 specification type,它用于根據(jù) ECMAScript 詞法嵌套代碼定義標(biāo)識符和特定的變量和函數(shù)之間的關(guān)聯(lián)。包含 Environment Record 和一個對外部 lexical environment 的 reference 兩個部分,當(dāng)一個 environment record 是 global environment record 時,引用的值為 null。體現(xiàn)在對 ECMAScript 規(guī)范的實現(xiàn)上,這個 Lexical Environment 就是一種數(shù)據(jù)結(jié)構(gòu)。通常,詞法環(huán)境與 ECMAScript 代碼的某些特定語法結(jié)構(gòu)(例如,function declaration,block statement 或 try statement 的 catch 子句)相關(guān)聯(lián),并且每次此類代碼被執(zhí)行時都會創(chuàng)建一個新的 lexical environment。
Environment Record
規(guī)范里,Environment Record 是一個 Record(Record 是 ECMAScript 的 specification type 之一,可以理解成由 key-value pairs 組成的集合),在一個簡單的面向?qū)ο蟮膶哟谓Y(jié)構(gòu)中,可以被認(rèn)為是一個具有三個實體子類的抽象類:
- Declaration Environment Record:通過 var、let、const、function、class、import 關(guān)鍵字聲明定義的 identifier 及其對應(yīng)的信息就記錄在 Declaration Environment Record 里
- Object Environment Record:與 with 語句相關(guān)
- Global Environment Record:全局最外層的 environment record,ECMAScript 內(nèi)置的對象和方法相關(guān)的信息就記錄在此
其中 Declaration Environment Record 又有兩個子類: - Function Environment Record:一個函數(shù)內(nèi)部最外層的 environment record
- Module Environment Record:與 Module 有關(guān)
正是這些類內(nèi)部的方法決定了執(zhí)行 ECMAScript 代碼時,通過一個 identifier 如何訪問到其對應(yīng)值的機制。
Execution Context
是一個 specification device,用于追蹤 ECMAScript 代碼的執(zhí)行。執(zhí)行 ECMAScript 代碼的過程中有可能有多個 execution contexts,這些execution contexts 通過棧來追蹤,每生成一個新的 execution context 便將其推入棧,同一時間只有棧頂?shù)哪莻€ execution contexts 出于運行中,運行結(jié)束之后便將之出棧。生成新的 execution context 的情況有三種:
- 執(zhí)行全局的 ECMAScript 代碼時
- 執(zhí)行 Module 代碼
- 執(zhí)行一個 function 里的代碼
每個 execution context 包含五個 component:
- code evaluation state
- Function:當(dāng)執(zhí)行的是 function 里的代碼時,值為對應(yīng)的 function object,否則為 null
- Realm:不好理解,一個 iframe 和其 parent 的 execution context 里的 Realm 是不相同的,比如在某個 iframe 里執(zhí)行
[1, 2, 3] instanceof window.parent.Array,結(jié)果是 false - VariableEnvironment:所有通過 var 聲明的 identifiers 組成的 environment record 所對應(yīng)的 lexical environment
- LexicalEnvironment::所有通過 let、const、class 等聲明的 identifiers 組成的 environment record 所對應(yīng)的 lexical environment
NOTE
- 在 let、const、class 聲明 identifier 的語句前訪問這些 identifier 會報錯,即使 outer lexical environment 里已經(jīng)有一個一樣的 identifier,這也是造成所謂「臨時性死區(qū)」的原因
- 只有 function 和 Module 里的 var 聲明的 identifier 不會被提升到 global environment record 里
- 一個新的 execution context 生成時,必至少有一個新的 lexical environment 隨之而生成,反之則不然
- 普通函數(shù)里的 this 值由該函數(shù)調(diào)用的方式?jīng)Q定
- 箭頭函數(shù)里的 this 值由該函數(shù)被聲明時所處的的 lexical environment 決定
參考: