8.3 执行上下文

一个执行上下文是由ECMAScript实现的一种用来追踪代码运行的机制。在任何时刻,都只有一个执行上下文是确实在执行代码的,就是所谓的运行时执行上下文

执行上下文栈是用来追踪执行上下文的。运行时执行上下文总是这个栈的栈顶元素。任何时候,当控制器从当前运行的执行环境相关的可执行代码转入与该执行环境无关的可执行代码时,会创建一个新的执行环境。新建的这个执行环境会推入栈中,成为当前的运行时执行上下文。

一个执行上下文包含任何追踪执行程序和它关联的代码状态。任何一个执行上下文最少都拥有表22中列出的组件。

表22 所有的执行上下文都具备的状态组件
组件 目的
代码执行状态 任何需要执行、挂起、恢复的和执行上下文关联的代码执行状态
函数 如果上下文是在执行函数对象代码,那这个组件的值就是这个函数对象。如果上下文是在执行Script或者Module,那这个值就是null
作用域 和代码对ECMAScript资源访问性相关联的Realm Record
ScriptOrModule 和源代码相关联的Module Record 或者 Script Record, 如果这没有源代码或者module,这种情况下执行上下文是在InitializeHostDefinedRealm,其值是null

在规范中定义了很多种情况会使运行时执行上下文挂起,一旦运行时被挂起,另一个执行上下文就会变成运行时上下文接手开始执行其代码。在一段时间以后,挂起的执行上下文又会成为运行时上下文继续在之前挂起的地方开始执行其代码。运行时上下文的切换一般如栈一样,以后进先出的规则。然而一ECMAScript功能要求非后进先出的形式进行运行时上下文的切换。

Realm 组件的值也叫做current Realm Record,函数组件的值也叫做active function object

ECMAScript代码执行上下文还有额外的状态组件如表23所示

表23 在ECMAScript代码上下文中额外的状态组件
组件 目的
词法环境 指定的用来处理上下文中代码的标识符引用的词法环境
变量环境 指定的其环境记录项持有上下文中的VariableStatements创建的绑定的词法环境

执行上下文中的词法环境和变量环境,总是词法环境。当执行上下文创建词法环境和变量环境的时候,它们的初始值是同样的。

当执行上下文正在执行generator对象时,会有一个额外的组件如表24所示

表24 Generator 执行上下文中额外的组件
组件 目的
Generator GeneratorObject 是这个执行上下文中正在执行的。

在绝大多数情况下,只有运行时执行上下文(执行上下文栈的栈顶元素)会在规范中被直接操作。所以,当“词法环境”,“变量环境”这两个术语在没有特殊说明的情况下,他们都是指运行时执行上下文中的这两个组件。

执行上下文是一个纯粹的标准机制,并不代表任何 ECMAScript 实现的东西。在 ECMAScript 程序中是不可能访问到执行环境的。

8.3.1 GetActiveScriptOrModule ()

这个抽象操作是基于 active function object,用来确定运行的脚本或者module,其执行步骤如下:

  1. 如果执行上下文栈是空, return null.
  2. 使 ec 为执行上下文栈中最顶层的那个Function component的 [[ScriptOrModule]] component 不为 null的那个执行上下文.
  3. 如果这样的执行上下文存在的话, 返回那个执行上下文Function组件的 [[ScriptOrModule]] 值.
  4. 否则, ec = running execution context.
  5. 断言: ec 的 ScriptOrModule component 不为 null.
  6. return ec’s ScriptOrModule component.

8.3.2 ResolveBinding(name [, env])

这个抽象操作是用来获取在词法环境中name的绑定,可选参数env可以作为搜索绑定的词法环境,执行过程如下:

  1. 如果env没有传或者为undefined,那么
    • env = running execution context 的 词法环境.
  2. 断言: env 是一个词法环境.
  3. 如果代码匹配的产生式是在严格模式下执行的,那么strict为true,否则为false。
  4. 返回 GetIdentifierReference(env, name, strict).

注意:ResolveBinding的返回值永远是一个Reference,并且其引用的名字为name

8.3.3 GetThisEnvironment ()

这个抽象操作是用来寻找当前提供了关键字this绑定的环境记录项。其执行步骤如下:

  1. lex = running execution context的词法环境。
  2. 重复如下步骤
    • envRec = lex.EnvironmentRecord
    • exists = envRec.HasThisBinding()
    • if exists === true, return envRec
    • outer = lex.外部词法环境
    • lex = outer

注意:循环一定会在第二步结束的,因为词法环境的最外层就是全局环境,全局环境有this的绑定

8.3.4 ResolveThisBinding ()

这个抽象操作是用来确定运行时执行上下文中的词法环境中的this关键字的绑定。其执行步骤如下:

  1. envRec = GetThisEnvironment().
  2. return envRec.GetThisBinding()

8.3.5 GetNewTarget ()

这个抽象操作用来确定运行时执行上下文中的词法环境中的NewTarget。其执行步骤如下:

  1. envRec = GetThisEnvironment( ).
  2. 断言: envRec 有 [[NewTarget]] 字段.
  3. 返回 envRec.[[NewTarget]].

8.3.6 GetGlobalObject ()

这个抽象操作用来确定运行时执行上下文中的词法环境中的全局对象。其执行步骤如下:

  1. ctx = running execution context.
  2. currentRealm = ctx’s Realm.
  3. 返回 currentRealm.[[GlobalObject]].