词法环境

2018-06-16 15:16 更新

词法环境 是一个用于定义特定变量和函数标识符在 ECMAScript 代码的词法嵌套结构上关联关系的规范类型。一个词法环境由一个环境记录项和可能为空的外部词法环境引用构成。通常词法环境会与特定的 ECMAScript 代码诸如 FunctionDeclaration,WithStatement 或者 TryStatement 的 Catch 块这样的语法结构相联系,且类似代码每次执行都会有一个新的语法环境被创建出来。

 环境记录项记录了在它的关联词法环境域内创建的标识符绑定情形。

 外部词法环境引用用于表示词法环境的逻辑嵌套关系模型。(内部)词法环境的外部引用是逻辑上包含内部词法环境的词法环境。外部词法环境自然也可能有多个内部词法环境。例如,如果一个 FunctionDeclaration 包含两个嵌套的 FunctionDeclaration,那么每个内嵌函数的词法环境都是外部函数本次执行所产生的词法环境。

 词法环境和环境记录项是纯粹的规范机制,而不需要 ECMAScript 的实现保持一致。ECMAScript 程序不可能直接访问或者更改这些值。

环境记录项

 在本标准中,共有 2 类环境记录项: 声明式环境记录项 和 对象式环境记录项 。声明式环境记录项用于定义那些将 标识符 与语言值直接绑定的 ECMA 脚本语法元素,例如 函数定义 , 变量定义 以及 Catch 语句。对象式环境记录项用于定义那些将 标识符 与具体对象的属性绑定的 ECMA 脚本元素,例如 程序 以及 With 表达式 。

 出于标准规范的目的,可以将环境记录项理解为面向对象中的一个简单继承结构,其中环境记录项是一个抽象类花前月下有 2 个具体实现类,分别为声明式环境记录项和对象式环境记录项。抽象类包含了表 17 所描述的抽象方法定义,针对每一个具体实现类,每个抽象方法都有不同的具体算法。

表17——环境记录项的抽象方法
方法作用
HasBinding(N)判断环境记录项是否包含对某个标识符的绑定。如果包含该绑定则返回 true,反之返回 false。其中字符串 N 是标识符文本。
CreateMutableBinding(N, D)
在环境记录项中创建一个新的可变绑定。其中字符串 N 指定绑定名称。如果可选参数 D 的值为true,则该绑定在后续操作中可以被删除。
SetMutableBinding(N,V, S)在环境记录项中设置一个已经存在的绑定的值。其中字符串 N 指定绑定名称。V 用于指定绑定的值,可以是任何 ECMA 脚本语言的类型。S 是一个布尔类型的标记,当 S 为 true 并且该绑定不允许赋值时,则抛出一个 TypeError 异常。S 用于指定是否为严格模式。
GetBindingValue(N,S)返回环境记录项中一个已经存在的绑定的值。其中字符串 N 指定绑定的名称。S 用于指定是否为严格模式。如果 S 的值为 true 并且该绑定不存在或未初始化,则抛出一个 ReferenceError 异常。
DeleteBinding(N)从环境记录项中删除一个绑定。其中字符串 N 指定绑定的名称。如果 N 指定的绑定存在,将其删除并返回 true。如果绑定存在但无法删除则返回false。如果绑定不存在则返回 true。
ImplicitThisValue()当从该环境记录项的绑定中获取一个函数对象并且调用时,该方法返回该函数对象使用的 this 对象的值。

声明式环境记录项

 每个声明式环境记录项都与一个包含变量和(或)函数声明的 ECMA 脚本的程序作用域相关联。声明式环境记录项用于绑定作用域内定义的一系列标识符。

 除了所有环境记录项都支持的可变绑定外,声明式环境记录项还提供不可变绑定。在不可变绑定中,一个标识符与它的值之间的关联关系建立之后,就无法改变。创建和初始化不可变绑定是两个独立的过程,因此类似的绑定可以处在已初始化阶段或者未初始化阶段。除了环境记录项定义的抽象方法外,声明式环境记录项还支持表 18 中列出的方法:

表18——声明式环境记录项的额外方法
方法作用
CreateImmutableBinding(N)在环境记录项中创建一个未初始化的不可变绑定。其中字符串 N 指定绑定名称。
InitializeImmutableBinding(N,V)在环境记录项中设置一个已经创建但未初始化的不可变绑定的值。其中字符串 N 指定绑定名称。V 用于指定绑定的值,可以是任何 ECMA 脚本语言的类型。

 环境记录项定义的方法的具体行为将由以下算法给予描述。

HasBinding (N)

 声明式环境记录项的 HasBinding 具体方法用于简单地判断作为参数的标识符是否是当前对象绑定的标识符之一:

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 如果 envRec 有一个名称为 N 的绑定,返回 true。
  3. 如果没有该绑定,返回 false。
CreateMutableBinding (N, D)

 声明式环境记录项的 CreateMutableBinding 具体方法会创建一个名称为 N 的绑定,并初始化其值为 undefined。方法调用时,当前环境记录项中不能存在 N 的绑定。如果调用时提供了布尔类型的参数 D 且其值为 true,则新建的绑定被标记为可删除。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 执行断言:envRec 没有 N 的绑定。
  3. 在 envRec 中为 N 创建一个可变绑定,并将绑定的值设置为 undefined。如果 D 为 true 则新创建的绑定可在后续操作中通过调用 DeleteBinding 删除。
SetMutableBinding (N,V,S)

 声明式环境记录项的 SetMutableBinding 具体方法尝试将当前名称为参数 N 的绑定的值修改为参数 V 指定的值。方法调用时,必须存在 N 的绑定。如果该绑定为不可变绑定,并且 S 的值为 true,则抛出一个 TypeError 异常。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 执行断言:envRec 必须有 N 的绑定。
  3. 如果 envRec 中 N 的绑定为可变绑定,则将其值修改为 V。
  4. 否则该操作会尝试修改一个不可变绑定的值,因此如果 S 的值为 true,则抛出一个 TypeError 异常。
GetBindingValue (N,S)

 声明式环境记录项的 GetBindingValue 具体方法简单地返回名称为参数 N 的绑定的值。方法调用时,该绑定必须存在。如果 S 的值为 true 且该绑定是一个未初始化的不可变绑定,则抛出一个 ReferenceError 异常。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 执行断言:envRec 必须有 N 的绑定。
  3. 如果 envRec 中 N 的绑定是一个未初始化的不可变绑定,则:如果 S 为 false,返回 undefined,否则抛出一个 ReferenceError 异常。
  4. 否则返回 envRec 中与 N 绑定的值。
DeleteBinding (N)

 声明式环境记录项的 DeleteBinding 具体方法只能删除显示指定可被删除的那些绑定。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 如果 envRec 不包含名称为 N 的绑定,返回 true。
  3. 如果 envRec 中 N 的绑定不能删除,返回 false。
  4. 移除 envRec 中 N 的绑定。
  5. 返回 true。
ImplicitThisValue()

 声明式环境记录项永远将 undefined 作为其 ImplicitThisValue 返回。

  1. 返回 undefined。
CreateImmutableBinding (N)

 声明式环境记录项的 CreateImmutableBinding 具体方法会创建一个不可变绑定,其名称为 N 且初始化其值为 undefined。调用方法时,该环境记录项中不得存在 N 的绑定。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 执行断言:envRec 不存在 N 的绑定。
  3. 在 envRec 中为 N 创建一个不可变绑定,并记录为未初始化。
InitializeImmutableBinding (N,V)

 声明式环境记录项的 InitializeImmutableBinding 具体方法用于将当前名称为参数 N 的绑定的值修改为参数 V 指定的值。方法调用时,必须存在 N 对应的未初始化的不可变绑定。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 执行断言:envRec 存在一个与 N 对应的未初始化的不可变绑定。
  3. 在 envRec 中将 N 的绑定的值设置为 V。
  4. 在 envRec 中将 N 的不可变绑定记录为已初始化。

对象式环境记录项

 每一个对象式环境记录项都有一个关联的对象,这个对象被称作 绑定对象 。对象式环境记录项直接将一系列标识符与其绑定对象的属性名称建立一一对应关系。不符合IdentifierName 的属性名不会作为绑定的标识符使用。无论是对象自身的,还是继承的属性都会作为绑定,无论该属性的 [[Enumerable]] 特性的值是什么。由于对象的属性可以动态的增减,因此对象式环境记录项所绑定的标识符集合也会隐匿地变化,这是增减绑定对象的属性而产生的副作用。通过以上描述的副作用而建立的绑定,均被视为可变绑定,即使该绑定对应的属性的 Writable 特性的值为 false。对象式环境记录项没有不可变绑定。

 对象式环境记录项可以通过配置的方式,将其绑定对象合为函数调用时的隐式 this 对象的值。这一功能用于规范 With 表达式(12.10 章 )引入的绑定行为。该行为通过对象式环境记录项中布尔类型的 provideThis 值控制,默认情况下,provideThis 的值为 false。

 环境记录项定义的方法的具体行为将由以下算法给予描述。

HasBinding(N)

 对象式环境记录项的 HasBinding 具体方法判断其关联的绑定对象是否有名为 N 的属性:

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 令 bindings 为 envRec 的绑定对象。
  3. 以 N 为属性名,调用 bindings 的 [[HasProperty]] 内部方法,并返回调用的结果。
CreateMutableBinding (N, D)

 对象式环境记录项的 CreateMutableBinding 具体方法会在其关联的绑定对象上创建一个名称为 N 的属性,并初始化其值为 undefined。调用方法时,绑定对象不得包含名称为 N的属性。如果调用方法时提供了布尔类型的参数 D 且其值为 true,则设置新创建的属性的 [[Configurable]] 特性的值为 true,否则设置为 false。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 令 bindings 为 envRec 的绑定对象。
  3. 执行断言:以 N 为属性名,调用 bindings 的 [[HasProperty]] 内部方法,调用的结果为 false。
  4. 如果 D 的值为 true,则令 configValue 的值为 true,否则令 configValue 的值为 false。
  5. 以 N、属性描述符 {[[Value]]:undefined, [[Writable]]: true, [[Enumerable]]: true , [[Configurable]]: configValue} 和布尔值 true 为参数,调用 bindings 的 [[DefineOwnProperty]] 内部方法。
SetMutableBinding (N,V,S)

 对象式环境记录项的 SetMutableBinding 具体方法会尝试设置其关联的绑定对象中名为 N 的属性的值为 V。方法调用时,绑定对象中应当存在该属性,如果该属性不存在或属性不可写,则根据 S 参数的值来执行错误处理。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 令 bindings 为 envRec 的绑定对象
  3. 以 N、V 和 S 为参数,调用 bindings 的 [[Put]] 内部方法。
GetBindingValue(N,S)

 对象式环境记录项的 GetBindingValue 具体方法返回其关联的绑定对象中名为 N 的属性的值。方法调用时,绑定对象中应当存在该属性,如果该属性不存在,则方法的返回值由 S参数决定:

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 令 bindings 为 envRec 的绑定对象
  3. 以 N 为属性名,调用 bindings 的 [[HasProperty]] 内部方法,并令 value 为调用的结果。
  4. 如果 value 的值为 false,则:如果 S 的值为 false,则返回 undefined,否则抛出一个 ReferenceError 异常。
  5. 以 N 为参数,调用 bindings 的 [[Get]] 内部方法,并返回调用的结果。
DeleteBinding (N)

 对象式环境记录项的 DeleteBinding 具体方法只能用于删除其关联的绑定对象上 [[Configurable]] 特性的值为 true 的属性所对应的绑定。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 令 bindings 为 envRec 的绑定对象
  3. 以 N 和布尔值 false 为参数,调用 bindings 的 [[Delete]] 内部方法。
ImplicitThisValue()

 对象式环境记录项的 ImplicitThisValue 通常返回 undefined,除非其 provideThis 标识的值为 true。

  1. 令 envRec 为函数调用时对应的声明式环境记录项。
  2. 如果 envRec 的 provideThis 标识的值为 true,返回 envRec 的绑定对象。
  3. 否则返回 undefined。

词法环境的运算

 在本标准中,以下抽象运算将被用于操作环境记录项:

GetIdentifierReference (lex, name, strict)

 当调用 GetIdentifierReference 抽象运算时,需要指定一个 词法环境 lex,一个标识符字符串 name 以及一个布尔型标识 strict。lex 的值可以为 null。当调用该运算时,按以下步骤进行:

  1. 如果 lex 的值为 null,则:返回一个类型为 引用 的对象,其基值为 undefined,引用的名称为 name,严格模式标识的值为 strict。
  2. 令 envRec 为 lex 的环境数据。
  3. 以 name 为参数 N,调用 envRec 的 HasBinding(N) 具体方法,并令 exists 为调用的结果。
  4. 如果 exists 为 true,则:返回一个类型为 引用 的对象,其基值为 envRec,引用的名称为 name,严格模式标识的值为 strict。
  5. 否则:令 outer 为 lex 的 外部环境引用 。以 outer、name 和 struct 为参数,调用 GetIdentifierReference,并返回调用的结果。

NewDeclarativeEnvironment (E)

 当调用 NewDeclarativeEnvironment 抽象运算时,需指定一个 词法环境 E,其值可以为 null,此时按以下步骤进行:

  1. 令 env 为一个新建的 词法环境 。
  2. 令 envRec 为一个新建的 声明式环境数据 ,该环境数据不包含任何绑定。
  3. 令 env 的环境数据为 envRec。
  4. 令 env 的外部词法环境引用至 E。
  5. 返回 env。

NewObjectEnvironment (O, E)

 当调用 NewObjectEnvironmentis 抽象运算时,需指定一个对象 O 及一个 词法环境 E(其值可以为 null),此时按以下步骤进行:

  1. 令 env 为一个新建的 词法环境 。
  2. 令 envRec 为一个新建的 对象环境数据 ,该环境数据包含 O 作为绑定对象。
  3. 令 env 的环境数据为 envRec。
  4. 令 env 的外部词法环境引用至 E。
  5. 返回 env。

全局环境

 全局环境 是一个唯一的 词法环境 ,它在任何 ECMA 脚本的代码执行前创建。全局环境的 环境数据 是一个 #object-environment-record 对象环境数据,该环境数据使用 全局对象(15.1)作为 绑定对象 。全局环境的 外部环境引用 为 null。

 在 ECMA 脚本的代码执行过程中,可能会向 全局对象 添加额外的属性,也可能修改其初始属性的值。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号