8.1 词法环境
词法环境是一个用于定义标识符和特定变量和函数在 ECMAScript 代码的词法嵌套结构上关联关系的规范类型。一个词法环境包括一个环境记录项和可能为null的外部词法环境的引用。通常,一个词法环境和ECMAScript代码中一些特殊语法结构相关,比如FunctionDeclaration, BlockStatement, TryStatement的Catch字句, 每次这类代码被执行时都会创建一个新的词法环境。
环境记录项记录了在其关联的词法环境范围中创建的标识符绑定。它被称作词法环境的EnvironmentRecord。
外层环境引用被用于表示词法环境的逻辑嵌套模型。(内层)词法环境的外层引用是逻辑上包括了内层词法环境的词法环境。一个外层词法环境自然也可能有它自身的外层词法环境。一个词法环境可能是多个内层词法环境的外部词法环境。比如,如果一个 FunctionDeclaraction 包含了2个 FunctionDeclaration, 那么每个内嵌函数的词法环境都是外部函数本次执行所产生的词法环境。
全局环境是一个没有外层环境的词法环境。全局环境的外层环境引用为null. 一个全局环境的环境记录项由标识符绑定和包括一个相关的全局对象初始组成,该全局对象的属性提供了一些全局环境的标识符绑定。当执行ECMAScript代码时,额外的属性允许被加入到全局对象中,并且初始属性可以被修改。
模块环境是一个词法环境,它包含模块的顶层声明的绑定。它也包含直接从模块导入的绑定。模块的外部环境是一个全局环境。
函数环境是一个词法环境,它对应于ECMAScript函数对象的调用。一个函数环境可能建立新的this绑定。一个函数环境也能捕捉支持super方法调用的状态。
词法环境和环境记录项的值是纯粹的标准机制,它不需要符合任何ECMAScript实现。ECMAScript程序不可以直接获取或改变这些值。
8.1.1 环境记录项
规范中有两种基本的环境记录项,声明式环境记录项(declarative Environment Records) 和 对象式(object Environment Records)。声明式环境记录项是用来定义将ECMAScript语言语法元素比如函数声明、变量声明和Catch子句直接和ECMAScript语言值相关联。对象式环境记录项用来定义将ECMAScript元素如With语句和object的属性相关联。全局环境记录项和函数环境记录项是特殊的用来规范脚本的全局声明和函数中的顶级声明。
出于标准规范的目的,环境记录项的值是Record这个规范类型的值。我们可以将环境记录项理解为面向对象中的一个简单继承结构,其中环境记录项是一个抽象类有 3 个具体实现子类,分别为声明式环境记录项、对象式环境记录项和全局环境记录项。函数环境记录项和模块环境记录项是声明式环境记录项的子类。抽象类包含了表 15 所描述的抽象方法,针对每一个具体实现类,每个抽象方法都有不同的具体算法。
表15 环境记录项的抽象方法
方法 | 目的 |
---|---|
HasBinding(N) | 判断环境记录项是否包含对字符串值 N 的绑定。如果包含该绑定则返回 true,反之返回 false。 |
CreateMutableBinding(N, D) | 在环境记录项中创建一个新的但是未初始化的可变绑定。其中字符串 N 指定绑定名称。如果参数 D 的值为true,则该绑定在后续操作中可以被删除。 |
CreateImmutableBinding(N, S) | 在环境记录项中创建一个新的但是未初始化的不可变绑定。其中字符串 N 指定绑定名称。如果参数 S 的值为true,未初始化时访问其值或者在初始化后又去设置其值,都会抛出异常,忽略这个操作时的严格模式的设定。 |
InitializeBinding(N, V) | 给一个已经存在但是没有初始化的环境记录项中的绑定设置值,N 是绑定的名称,V 是要设置的值,并且可以是任意ECMAScript语言类型 |
SetMutableBinding(N, V, S) | 在环境记录项中设置一个已经存在的可变绑定的值。其中字符串 N 指定绑定名称。V 用于指定绑定的值,可以是任何 ECMAScript语言类型。S 是一个布尔类型的标记,当 S 为 true 并且该绑定不允许赋值时,则抛出一个 TypeError 异常。 |
GetBindingValue(N,S) | 返回环境记录项中一个已经存在的绑定的值。其中字符串 N 指定绑定的名称。S 用于指定是否为严格模式。如果 S 的值为 true 并且该绑定不存在,则抛出一个 ReferenceError 异常。如果绑定存在但是没有初始化,会抛出一个ReferenceError 异常。忽略 S 的值 |
DeleteBinding(N) | 从环境记录项中删除一个绑定。其中字符串 N 指定绑定的名称。如果 N 指定的绑定存在,将其删除并返回 true。如果绑定存在但无法删除则返回false。如果绑定不存在则返回 true。 |
HasThisBinding() | 判断环境记录项中是否已经有this绑定,如果有返回true,否则返回false |
HasSuperBinding() | 判断环境记录项中是否已经有 super 绑定 ,如果有则返回true,否则返回false |
WithBaseObject() | 如果环境记录项是关联于一个with语句,返回with 对象,否则返回undefined |
8.1.1.1 声明式环境记录项
每个声明式环境记录项都和ECMAScript程序方位内的变量、常量、let、class、module、import或者函数声明相关联。一个声明式环境记录项绑定了一序列在其范围内的声明的标识符。