Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重学js——执行上下文(Execution Contexts) #50

Open
lizhongzhen11 opened this issue Oct 27, 2019 · 0 comments
Open

重学js——执行上下文(Execution Contexts) #50

lizhongzhen11 opened this issue Oct 27, 2019 · 0 comments
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN

Comments

@lizhongzhen11
Copy link
Owner

lizhongzhen11 commented Oct 27, 2019

Execution Contexts

执行上下文是一种规范机制,用于跟踪对代码的运行时求值,通过ECMAScript的某种实现。在任何时间点,每个实际执行代码的代理最多有一个执行上下文。这就是代理运行时执行上下文

执行上下文栈用于跟踪执行上下文。运行时执行上下文总是位于栈的顶部。 当控制权从与当前运行时执行上下文关联的可执行代码转移到与执行上下文无关的可执行代码时,会创建新的执行上下文(可以认为,每个可执行代码都有与之关联的执行上下文)。最新被创建的执行上下文会被push到栈顶,成为运行时执行上下文。

每个执行上下文至少有下表中列出的状态组成:

组成部分 意义
code evaluation state 执行、挂起和恢复与此执行上下文关联的代码计算所需的任何状态。
Function 如果执行上下文正在计算函数对象,那么该 Function 的值就是那个函数对象。如果上下文正在计算脚本或者,那么 Function 的值就是 null
Realm(领域) 关联代码从中访问ECMAScript资源的领域记录。
ScriptOrModule 关联代码的模块记录或者脚本记录。如果没有原始脚本或模块,那么与在InitializeHostDefinedRealm中创建的原始执行上下文一样,该 ScriptOrModule值为 null

伪代码大致是这样的:

// 执行上下文
EC = [
  state
  fun
  realm
  null
];
// 执行上下文栈。EC1,EC2,EC3都是伪代码模拟执行上下文
ECStack = [
  EC1,
  EC2
  ...
];
// 后进先出
ECStack.push(EC3) // EC3放到栈顶
ECStack.pop() // EC3先执行完出来

一旦运行时执行上下文被挂起,另一个不同的执行上下文会成为新的 运行时执行上下文 并且开始执行属于它的代码。以后某个时段,被挂起的执行上下文可能再次成为运行时执行上下文并且在它之前被挂起的地方继续计算它的代码。运行时执行上下文状态在执行上下文之间的转换通常以类似于后进先出的栈方式进行。然而,一些ECMAScript特性需要运行时执行上下文的非后进先出转换。

活跃的函数对象

运行时执行上下文领域部分的值也被称为当前领域记录(the current Realm Record)。运行时执行上下文的 Function 部分的值也被叫做 活跃的函数对象(the active function object)

ECMAScript代码的执行上下文还有额外的状态组成部分,看下表:

组成部分 意义
LexicalEnvironment 词法环境的标识符,用于解析在此执行上下文中由代码生成的标识符引用。
VariableEnvironment 词法环境的标识符,其EnvironmentRecord保存此执行上下文中由VariableStatement创建的绑定。

注意:LexicalEnvironment和VariableEnvironment全都是词法环境。

表示生成器对象求值的执行上下文有额外的状态部分,看下表:

组成部分 意义
Generator 此执行上下文正在计算的GeneratorObject

执行上下文纯粹是一种规范机制,不需要与ECMAScript实现的任何特定工件相对应。ECMAScript代码是无法直接获取或者观察到执行上下文的。

ResolveBinding(name [ , env ])

该抽象运算用来决定传入的字符串 name 绑定。可选参数 env 明确提供用于绑定的 词法环境

  1. 如果 env 不存在,或为 undefined
    1. env 设为 运行时执行上下文词法环境
  2. 断言:env词法环境
  3. 如果严格模式代码中包含与要求值的语法产生相匹配的代码,定义 stricttrue,否则为 false
  4. 返回 ? GetIdentifierReference(env, name, strict)

GetThisEnvironment()

该抽象运算会查找用于当前提供给 this 关键字绑定的 环境记录

  1. 定义 lex运行时执行上下文 的词法环境
  2. 重复,
  3. 定义 envReclex环境记录
  4. 定义 existsenvRec.HasThisBinding()
  5. 如果 existstrue,返回 envRec
  6. 定义 outerlex 的外部环境引用值
  7. 断言:outernull
  8. lex 赋值给 outer

注意:步骤2中的循环最终会终止,因为 环境列表始终以具有 this 绑定的 全局环境 结尾

ResolveThisBinding()

  1. 定义 envRecGetThisEnvironment()
  2. 返回 ? envRec.GetThisBinding()

拓展阅读

JavaScript深入之执行上下文栈——冴羽

注意

  1. 在网上看到一些文章说 执行上下文总共有三种类型?,这一点我在规范中没有找到,暂时不知为何他们会得出这个结论。
  2. 个人感觉,拓展阅读里的最后思考题,第二个函数执行上下文入栈出栈应该是这样的:
ECStack.push(<checkscope> functionContext);
ECStack.pop();
ECStack.push(<checkscope> functionContext);
ECStack.push(<f> functionContext);
ECStack.pop();
ECStack.pop();
// 函数f涉及到闭包,它的词法环境会有对checkscope环境的引用,它的直接父级始终是checkscope。
@lizhongzhen11 lizhongzhen11 added the js基础 Good for newcomers label Oct 27, 2019
@lizhongzhen11 lizhongzhen11 added the 重学js 重学js系列 规范+MDN label Jan 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN
Projects
None yet
Development

No branches or pull requests

1 participant