詞法環(huán)境

2018-06-16 15:16 更新

詞法環(huán)境 是一個(gè)用于定義特定變量和函數(shù)標(biāo)識符在 ECMAScript 代碼的詞法嵌套結(jié)構(gòu)上關(guān)聯(lián)關(guān)系的規(guī)范類型。一個(gè)詞法環(huán)境由一個(gè)環(huán)境記錄項(xiàng)和可能為空的外部詞法環(huán)境引用構(gòu)成。通常詞法環(huán)境會(huì)與特定的 ECMAScript 代碼諸如 FunctionDeclaration,WithStatement 或者 TryStatement 的 Catch 塊這樣的語法結(jié)構(gòu)相聯(lián)系,且類似代碼每次執(zhí)行都會(huì)有一個(gè)新的語法環(huán)境被創(chuàng)建出來。

 環(huán)境記錄項(xiàng)記錄了在它的關(guān)聯(lián)詞法環(huán)境域內(nèi)創(chuàng)建的標(biāo)識符綁定情形。

 外部詞法環(huán)境引用用于表示詞法環(huán)境的邏輯嵌套關(guān)系模型。(內(nèi)部)詞法環(huán)境的外部引用是邏輯上包含內(nèi)部詞法環(huán)境的詞法環(huán)境。外部詞法環(huán)境自然也可能有多個(gè)內(nèi)部詞法環(huán)境。例如,如果一個(gè) FunctionDeclaration 包含兩個(gè)嵌套的 FunctionDeclaration,那么每個(gè)內(nèi)嵌函數(shù)的詞法環(huán)境都是外部函數(shù)本次執(zhí)行所產(chǎn)生的詞法環(huán)境。

 詞法環(huán)境和環(huán)境記錄項(xiàng)是純粹的規(guī)范機(jī)制,而不需要 ECMAScript 的實(shí)現(xiàn)保持一致。ECMAScript 程序不可能直接訪問或者更改這些值。

環(huán)境記錄項(xiàng)

 在本標(biāo)準(zhǔn)中,共有 2 類環(huán)境記錄項(xiàng): 聲明式環(huán)境記錄項(xiàng) 和 對象式環(huán)境記錄項(xiàng) 。聲明式環(huán)境記錄項(xiàng)用于定義那些將 標(biāo)識符 與語言值直接綁定的 ECMA 腳本語法元素,例如 函數(shù)定義 , 變量定義 以及 Catch 語句。對象式環(huán)境記錄項(xiàng)用于定義那些將 標(biāo)識符 與具體對象的屬性綁定的 ECMA 腳本元素,例如 程序 以及 With 表達(dá)式 。

 出于標(biāo)準(zhǔn)規(guī)范的目的,可以將環(huán)境記錄項(xiàng)理解為面向?qū)ο笾械囊粋€(gè)簡單繼承結(jié)構(gòu),其中環(huán)境記錄項(xiàng)是一個(gè)抽象類花前月下有 2 個(gè)具體實(shí)現(xiàn)類,分別為聲明式環(huán)境記錄項(xiàng)和對象式環(huán)境記錄項(xiàng)。抽象類包含了表 17 所描述的抽象方法定義,針對每一個(gè)具體實(shí)現(xiàn)類,每個(gè)抽象方法都有不同的具體算法。

表17——環(huán)境記錄項(xiàng)的抽象方法
方法作用
HasBinding(N)判斷環(huán)境記錄項(xiàng)是否包含對某個(gè)標(biāo)識符的綁定。如果包含該綁定則返回 true,反之返回 false。其中字符串 N 是標(biāo)識符文本。
CreateMutableBinding(N, D)
在環(huán)境記錄項(xiàng)中創(chuàng)建一個(gè)新的可變綁定。其中字符串 N 指定綁定名稱。如果可選參數(shù) D 的值為true,則該綁定在后續(xù)操作中可以被刪除。
SetMutableBinding(N,V, S)在環(huán)境記錄項(xiàng)中設(shè)置一個(gè)已經(jīng)存在的綁定的值。其中字符串 N 指定綁定名稱。V 用于指定綁定的值,可以是任何 ECMA 腳本語言的類型。S 是一個(gè)布爾類型的標(biāo)記,當(dāng) S 為 true 并且該綁定不允許賦值時(shí),則拋出一個(gè) TypeError 異常。S 用于指定是否為嚴(yán)格模式。
GetBindingValue(N,S)返回環(huán)境記錄項(xiàng)中一個(gè)已經(jīng)存在的綁定的值。其中字符串 N 指定綁定的名稱。S 用于指定是否為嚴(yán)格模式。如果 S 的值為 true 并且該綁定不存在或未初始化,則拋出一個(gè) ReferenceError 異常。
DeleteBinding(N)從環(huán)境記錄項(xiàng)中刪除一個(gè)綁定。其中字符串 N 指定綁定的名稱。如果 N 指定的綁定存在,將其刪除并返回 true。如果綁定存在但無法刪除則返回false。如果綁定不存在則返回 true。
ImplicitThisValue()當(dāng)從該環(huán)境記錄項(xiàng)的綁定中獲取一個(gè)函數(shù)對象并且調(diào)用時(shí),該方法返回該函數(shù)對象使用的 this 對象的值。

聲明式環(huán)境記錄項(xiàng)

 每個(gè)聲明式環(huán)境記錄項(xiàng)都與一個(gè)包含變量和(或)函數(shù)聲明的 ECMA 腳本的程序作用域相關(guān)聯(lián)。聲明式環(huán)境記錄項(xiàng)用于綁定作用域內(nèi)定義的一系列標(biāo)識符。

 除了所有環(huán)境記錄項(xiàng)都支持的可變綁定外,聲明式環(huán)境記錄項(xiàng)還提供不可變綁定。在不可變綁定中,一個(gè)標(biāo)識符與它的值之間的關(guān)聯(lián)關(guān)系建立之后,就無法改變。創(chuàng)建和初始化不可變綁定是兩個(gè)獨(dú)立的過程,因此類似的綁定可以處在已初始化階段或者未初始化階段。除了環(huán)境記錄項(xiàng)定義的抽象方法外,聲明式環(huán)境記錄項(xiàng)還支持表 18 中列出的方法:

表18——聲明式環(huán)境記錄項(xiàng)的額外方法
方法作用
CreateImmutableBinding(N)在環(huán)境記錄項(xiàng)中創(chuàng)建一個(gè)未初始化的不可變綁定。其中字符串 N 指定綁定名稱。
InitializeImmutableBinding(N,V)在環(huán)境記錄項(xiàng)中設(shè)置一個(gè)已經(jīng)創(chuàng)建但未初始化的不可變綁定的值。其中字符串 N 指定綁定名稱。V 用于指定綁定的值,可以是任何 ECMA 腳本語言的類型。

 環(huán)境記錄項(xiàng)定義的方法的具體行為將由以下算法給予描述。

HasBinding (N)

 聲明式環(huán)境記錄項(xiàng)的 HasBinding 具體方法用于簡單地判斷作為參數(shù)的標(biāo)識符是否是當(dāng)前對象綁定的標(biāo)識符之一:

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 如果 envRec 有一個(gè)名稱為 N 的綁定,返回 true。
  3. 如果沒有該綁定,返回 false。
CreateMutableBinding (N, D)

 聲明式環(huán)境記錄項(xiàng)的 CreateMutableBinding 具體方法會(huì)創(chuàng)建一個(gè)名稱為 N 的綁定,并初始化其值為 undefined。方法調(diào)用時(shí),當(dāng)前環(huán)境記錄項(xiàng)中不能存在 N 的綁定。如果調(diào)用時(shí)提供了布爾類型的參數(shù) D 且其值為 true,則新建的綁定被標(biāo)記為可刪除。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 執(zhí)行斷言:envRec 沒有 N 的綁定。
  3. 在 envRec 中為 N 創(chuàng)建一個(gè)可變綁定,并將綁定的值設(shè)置為 undefined。如果 D 為 true 則新創(chuàng)建的綁定可在后續(xù)操作中通過調(diào)用 DeleteBinding 刪除。
SetMutableBinding (N,V,S)

 聲明式環(huán)境記錄項(xiàng)的 SetMutableBinding 具體方法嘗試將當(dāng)前名稱為參數(shù) N 的綁定的值修改為參數(shù) V 指定的值。方法調(diào)用時(shí),必須存在 N 的綁定。如果該綁定為不可變綁定,并且 S 的值為 true,則拋出一個(gè) TypeError 異常。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 執(zhí)行斷言:envRec 必須有 N 的綁定。
  3. 如果 envRec 中 N 的綁定為可變綁定,則將其值修改為 V。
  4. 否則該操作會(huì)嘗試修改一個(gè)不可變綁定的值,因此如果 S 的值為 true,則拋出一個(gè) TypeError 異常。
GetBindingValue (N,S)

 聲明式環(huán)境記錄項(xiàng)的 GetBindingValue 具體方法簡單地返回名稱為參數(shù) N 的綁定的值。方法調(diào)用時(shí),該綁定必須存在。如果 S 的值為 true 且該綁定是一個(gè)未初始化的不可變綁定,則拋出一個(gè) ReferenceError 異常。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 執(zhí)行斷言:envRec 必須有 N 的綁定。
  3. 如果 envRec 中 N 的綁定是一個(gè)未初始化的不可變綁定,則:如果 S 為 false,返回 undefined,否則拋出一個(gè) ReferenceError 異常。
  4. 否則返回 envRec 中與 N 綁定的值。
DeleteBinding (N)

 聲明式環(huán)境記錄項(xiàng)的 DeleteBinding 具體方法只能刪除顯示指定可被刪除的那些綁定。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 如果 envRec 不包含名稱為 N 的綁定,返回 true。
  3. 如果 envRec 中 N 的綁定不能刪除,返回 false。
  4. 移除 envRec 中 N 的綁定。
  5. 返回 true。
ImplicitThisValue()

 聲明式環(huán)境記錄項(xiàng)永遠(yuǎn)將 undefined 作為其 ImplicitThisValue 返回。

  1. 返回 undefined。
CreateImmutableBinding (N)

 聲明式環(huán)境記錄項(xiàng)的 CreateImmutableBinding 具體方法會(huì)創(chuàng)建一個(gè)不可變綁定,其名稱為 N 且初始化其值為 undefined。調(diào)用方法時(shí),該環(huán)境記錄項(xiàng)中不得存在 N 的綁定。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 執(zhí)行斷言:envRec 不存在 N 的綁定。
  3. 在 envRec 中為 N 創(chuàng)建一個(gè)不可變綁定,并記錄為未初始化。
InitializeImmutableBinding (N,V)

 聲明式環(huán)境記錄項(xiàng)的 InitializeImmutableBinding 具體方法用于將當(dāng)前名稱為參數(shù) N 的綁定的值修改為參數(shù) V 指定的值。方法調(diào)用時(shí),必須存在 N 對應(yīng)的未初始化的不可變綁定。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 執(zhí)行斷言:envRec 存在一個(gè)與 N 對應(yīng)的未初始化的不可變綁定。
  3. 在 envRec 中將 N 的綁定的值設(shè)置為 V。
  4. 在 envRec 中將 N 的不可變綁定記錄為已初始化。

對象式環(huán)境記錄項(xiàng)

 每一個(gè)對象式環(huán)境記錄項(xiàng)都有一個(gè)關(guān)聯(lián)的對象,這個(gè)對象被稱作 綁定對象 。對象式環(huán)境記錄項(xiàng)直接將一系列標(biāo)識符與其綁定對象的屬性名稱建立一一對應(yīng)關(guān)系。不符合IdentifierName 的屬性名不會(huì)作為綁定的標(biāo)識符使用。無論是對象自身的,還是繼承的屬性都會(huì)作為綁定,無論該屬性的 [[Enumerable]] 特性的值是什么。由于對象的屬性可以動(dòng)態(tài)的增減,因此對象式環(huán)境記錄項(xiàng)所綁定的標(biāo)識符集合也會(huì)隱匿地變化,這是增減綁定對象的屬性而產(chǎn)生的副作用。通過以上描述的副作用而建立的綁定,均被視為可變綁定,即使該綁定對應(yīng)的屬性的 Writable 特性的值為 false。對象式環(huán)境記錄項(xiàng)沒有不可變綁定。

 對象式環(huán)境記錄項(xiàng)可以通過配置的方式,將其綁定對象合為函數(shù)調(diào)用時(shí)的隱式 this 對象的值。這一功能用于規(guī)范 With 表達(dá)式(12.10 章 )引入的綁定行為。該行為通過對象式環(huán)境記錄項(xiàng)中布爾類型的 provideThis 值控制,默認(rèn)情況下,provideThis 的值為 false。

 環(huán)境記錄項(xiàng)定義的方法的具體行為將由以下算法給予描述。

HasBinding(N)

 對象式環(huán)境記錄項(xiàng)的 HasBinding 具體方法判斷其關(guān)聯(lián)的綁定對象是否有名為 N 的屬性:

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 令 bindings 為 envRec 的綁定對象。
  3. 以 N 為屬性名,調(diào)用 bindings 的 [[HasProperty]] 內(nèi)部方法,并返回調(diào)用的結(jié)果。
CreateMutableBinding (N, D)

 對象式環(huán)境記錄項(xiàng)的 CreateMutableBinding 具體方法會(huì)在其關(guān)聯(lián)的綁定對象上創(chuàng)建一個(gè)名稱為 N 的屬性,并初始化其值為 undefined。調(diào)用方法時(shí),綁定對象不得包含名稱為 N的屬性。如果調(diào)用方法時(shí)提供了布爾類型的參數(shù) D 且其值為 true,則設(shè)置新創(chuàng)建的屬性的 [[Configurable]] 特性的值為 true,否則設(shè)置為 false。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 令 bindings 為 envRec 的綁定對象。
  3. 執(zhí)行斷言:以 N 為屬性名,調(diào)用 bindings 的 [[HasProperty]] 內(nèi)部方法,調(diào)用的結(jié)果為 false。
  4. 如果 D 的值為 true,則令 configValue 的值為 true,否則令 configValue 的值為 false。
  5. 以 N、屬性描述符 {[[Value]]:undefined, [[Writable]]: true, [[Enumerable]]: true , [[Configurable]]: configValue} 和布爾值 true 為參數(shù),調(diào)用 bindings 的 [[DefineOwnProperty]] 內(nèi)部方法。
SetMutableBinding (N,V,S)

 對象式環(huán)境記錄項(xiàng)的 SetMutableBinding 具體方法會(huì)嘗試設(shè)置其關(guān)聯(lián)的綁定對象中名為 N 的屬性的值為 V。方法調(diào)用時(shí),綁定對象中應(yīng)當(dāng)存在該屬性,如果該屬性不存在或?qū)傩圆豢蓪懀瑒t根據(jù) S 參數(shù)的值來執(zhí)行錯(cuò)誤處理。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 令 bindings 為 envRec 的綁定對象
  3. 以 N、V 和 S 為參數(shù),調(diào)用 bindings 的 [[Put]] 內(nèi)部方法。
GetBindingValue(N,S)

 對象式環(huán)境記錄項(xiàng)的 GetBindingValue 具體方法返回其關(guān)聯(lián)的綁定對象中名為 N 的屬性的值。方法調(diào)用時(shí),綁定對象中應(yīng)當(dāng)存在該屬性,如果該屬性不存在,則方法的返回值由 S參數(shù)決定:

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 令 bindings 為 envRec 的綁定對象
  3. 以 N 為屬性名,調(diào)用 bindings 的 [[HasProperty]] 內(nèi)部方法,并令 value 為調(diào)用的結(jié)果。
  4. 如果 value 的值為 false,則:如果 S 的值為 false,則返回 undefined,否則拋出一個(gè) ReferenceError 異常。
  5. 以 N 為參數(shù),調(diào)用 bindings 的 [[Get]] 內(nèi)部方法,并返回調(diào)用的結(jié)果。
DeleteBinding (N)

 對象式環(huán)境記錄項(xiàng)的 DeleteBinding 具體方法只能用于刪除其關(guān)聯(lián)的綁定對象上 [[Configurable]] 特性的值為 true 的屬性所對應(yīng)的綁定。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 令 bindings 為 envRec 的綁定對象
  3. 以 N 和布爾值 false 為參數(shù),調(diào)用 bindings 的 [[Delete]] 內(nèi)部方法。
ImplicitThisValue()

 對象式環(huán)境記錄項(xiàng)的 ImplicitThisValue 通常返回 undefined,除非其 provideThis 標(biāo)識的值為 true。

  1. 令 envRec 為函數(shù)調(diào)用時(shí)對應(yīng)的聲明式環(huán)境記錄項(xiàng)。
  2. 如果 envRec 的 provideThis 標(biāo)識的值為 true,返回 envRec 的綁定對象。
  3. 否則返回 undefined。

詞法環(huán)境的運(yùn)算

 在本標(biāo)準(zhǔn)中,以下抽象運(yùn)算將被用于操作環(huán)境記錄項(xiàng):

GetIdentifierReference (lex, name, strict)

 當(dāng)調(diào)用 GetIdentifierReference 抽象運(yùn)算時(shí),需要指定一個(gè) 詞法環(huán)境 lex,一個(gè)標(biāo)識符字符串 name 以及一個(gè)布爾型標(biāo)識 strict。lex 的值可以為 null。當(dāng)調(diào)用該運(yùn)算時(shí),按以下步驟進(jìn)行:

  1. 如果 lex 的值為 null,則:返回一個(gè)類型為 引用 的對象,其基值為 undefined,引用的名稱為 name,嚴(yán)格模式標(biāo)識的值為 strict。
  2. 令 envRec 為 lex 的環(huán)境數(shù)據(jù)。
  3. 以 name 為參數(shù) N,調(diào)用 envRec 的 HasBinding(N) 具體方法,并令 exists 為調(diào)用的結(jié)果。
  4. 如果 exists 為 true,則:返回一個(gè)類型為 引用 的對象,其基值為 envRec,引用的名稱為 name,嚴(yán)格模式標(biāo)識的值為 strict。
  5. 否則:令 outer 為 lex 的 外部環(huán)境引用 。以 outer、name 和 struct 為參數(shù),調(diào)用 GetIdentifierReference,并返回調(diào)用的結(jié)果。

NewDeclarativeEnvironment (E)

 當(dāng)調(diào)用 NewDeclarativeEnvironment 抽象運(yùn)算時(shí),需指定一個(gè) 詞法環(huán)境 E,其值可以為 null,此時(shí)按以下步驟進(jìn)行:

  1. 令 env 為一個(gè)新建的 詞法環(huán)境 。
  2. 令 envRec 為一個(gè)新建的 聲明式環(huán)境數(shù)據(jù) ,該環(huán)境數(shù)據(jù)不包含任何綁定。
  3. 令 env 的環(huán)境數(shù)據(jù)為 envRec。
  4. 令 env 的外部詞法環(huán)境引用至 E。
  5. 返回 env。

NewObjectEnvironment (O, E)

 當(dāng)調(diào)用 NewObjectEnvironmentis 抽象運(yùn)算時(shí),需指定一個(gè)對象 O 及一個(gè) 詞法環(huán)境 E(其值可以為 null),此時(shí)按以下步驟進(jìn)行:

  1. 令 env 為一個(gè)新建的 詞法環(huán)境 。
  2. 令 envRec 為一個(gè)新建的 對象環(huán)境數(shù)據(jù) ,該環(huán)境數(shù)據(jù)包含 O 作為綁定對象。
  3. 令 env 的環(huán)境數(shù)據(jù)為 envRec。
  4. 令 env 的外部詞法環(huán)境引用至 E。
  5. 返回 env。

全局環(huán)境

 全局環(huán)境 是一個(gè)唯一的 詞法環(huán)境 ,它在任何 ECMA 腳本的代碼執(zhí)行前創(chuàng)建。全局環(huán)境的 環(huán)境數(shù)據(jù) 是一個(gè) #object-environment-record 對象環(huán)境數(shù)據(jù),該環(huán)境數(shù)據(jù)使用 全局對象(15.1)作為 綁定對象 。全局環(huán)境的 外部環(huán)境引用 為 null。

 在 ECMA 腳本的代碼執(zhí)行過程中,可能會(huì)向 全局對象 添加額外的屬性,也可能修改其初始屬性的值。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號