执行上下文
变量和函数的执行上下文决定了它们可以访问哪些数据,以及它们的行为 ——《JavaScript 高级程序设计》
简而言之,执行上下文是评估和执行 JavaScript 代码的环境的抽象概念。每当 Javascript 代码在运行的时候,它都是在执行上下文中运行。
类型
JavaScript 中有三种执行上下文类型。
- 全局执行上下文
- 函数执行上下文
- Eval 函数执行上下文
组成
在 ES2018 中执行上下文的组成如下:
- lexical environment:词法环境,当获取变量或者 this 值时使用。
- variable environment:变量环境,当声明变量时使用。
- code evaluation state:用于恢复代码执行位置。
- Function:执行的任务是函数时使用,表示正在被执行的函数。
- ScriptOrModule:执行的任务是脚本或者模块时使用,表示正在被执行的代码。
- Realm:使用的基础库和内置对象实例。
- Generator:仅生成器上下文有这个属性,表示当前生成器。
创建
-
this 值的决定,即 this 绑定。
- 在全局执行上下文中,
this的值指向全局对象。(在浏览器中,this引用 Window 对象)。 - 在函数执行上下文中,
this的值取决于该函数是如何被调用的。如果它被一个引用对象调用,那么this会被设置成那个对象,否则this的值被设置为全局对象或者undefined(在严格模式下)。
- 在全局执行上下文中,
-
创建词法环境。
ES6 中
let和const声明的变量会挂载到词法环境当中。词法环境 ES6 官方定义中,词法环境是一种规范类型,基于 ECMAScript 代码的词法嵌套结构来定义标识符(变量和函数的名称)和具体变量和函数的关联。简单来说词法环境是一种持有标识符-变量映射的结构。在词法环境的内部有两个组件:
- 环境记录器:存储变量和函数声明的实际位置。
- 外部环境的引用:意味着它可以访问其父级词法环境(作用域)。
-
创建变量环境。
同样是一个词法环境,只用来存储 var 变量绑定,其环境记录器持有变量声明语句在执行上下文中创建的绑定关系。
执行栈
JS 引擎在运行 JS 代码时还会维护一个执行上下文栈(Execution context stack,ECS)。执行栈是一种拥有 LIFO(后进先出)数据结构的栈,被用来存储代码运行时创建的所有执行上下文。
执行栈管理执行上下文:
- 当 JS 引擎启动脚本时,它会创建一个全局执行上下文并压入执行栈。
- 当一个函数被调用时,JS 引擎会创建一个函数执行上下文并压入执行栈顶部。
- 当该函数执行结束时,执行上下文从栈中弹出,控制流程到达当前栈中的下一个上下文。