JavaScript 之执行上下文

80 阅读3分钟

执行上下文

变量和函数的执行上下文决定了它们可以访问哪些数据,以及它们的行为 ——《JavaScript 高级程序设计》

简而言之,执行上下文是评估和执行 JavaScript 代码的环境的抽象概念。每当 Javascript 代码在运行的时候,它都是在执行上下文中运行。

类型

JavaScript 中有三种执行上下文类型。

  • 全局执行上下文
  • 函数执行上下文
  • Eval 函数执行上下文

组成

在 ES2018 中执行上下文的组成如下:

  • lexical environment:词法环境,当获取变量或者 this 值时使用。
  • variable environment:变量环境,当声明变量时使用。
  • code evaluation state:用于恢复代码执行位置。
  • Function:执行的任务是函数时使用,表示正在被执行的函数。
  • ScriptOrModule:执行的任务是脚本或者模块时使用,表示正在被执行的代码。
  • Realm:使用的基础库和内置对象实例。
  • Generator:仅生成器上下文有这个属性,表示当前生成器。

创建

  1. this 值的决定,即 this 绑定

    • 在全局执行上下文中,this 的值指向全局对象。(在浏览器中,this引用 Window 对象)。
    • 在函数执行上下文中,this 的值取决于该函数是如何被调用的。如果它被一个引用对象调用,那么 this 会被设置成那个对象,否则 this 的值被设置为全局对象或者 undefined(在严格模式下)。
  2. 创建词法环境

    ES6 中letconst声明的变量会挂载到词法环境当中。

    词法环境 ES6 官方定义中,词法环境是一种规范类型,基于 ECMAScript 代码的词法嵌套结构来定义标识符(变量和函数的名称)和具体变量和函数的关联。简单来说词法环境是一种持有标识符-变量映射的结构。在词法环境的内部有两个组件:

    1. 环境记录器:存储变量和函数声明的实际位置。
    2. 外部环境的引用:意味着它可以访问其父级词法环境(作用域)。
  3. 创建变量环境

    同样是一个词法环境,只用来存储 var 变量绑定,其环境记录器持有变量声明语句在执行上下文中创建的绑定关系。

执行栈

JS 引擎在运行 JS 代码时还会维护一个执行上下文栈(Execution context stack,ECS)。执行栈是一种拥有 LIFO(后进先出)数据结构的栈,被用来存储代码运行时创建的所有执行上下文。

执行栈管理执行上下文:

  1. 当 JS 引擎启动脚本时,它会创建一个全局执行上下文并压入执行栈。
  2. 当一个函数被调用时,JS 引擎会创建一个函数执行上下文并压入执行栈顶部。
  3. 当该函数执行结束时,执行上下文从栈中弹出,控制流程到达当前栈中的下一个上下文。