一、执行上下文的创建
执行上下文的创建分为两个阶段:
⦿ 创建阶段
⦿ 执行阶段
1.创建阶段
简单来说:在创建阶段,JS引擎只是扫描整个代码,但是不执行。它创建作用域链,并且为其作用域内每个变量和函数分配内存。之后,还初始化 this 的值。
(1)创建阶段做两件事情:
⦿ 创建词法环境
⦿ 创建变量环境,变量环境是也是一种词法环境。
执行上下文 = {
词法环境 = <对内存中的词法环境的引用>,
变量环境 = <对内存中的变量环境的引用>,
}
(2)词法环境:
① 每个执行上下文都有一个相关联的词法环境(简称环境)。
②词法环境的定义:用于定义出现在上下文中的标识符与其值之间的关联的结构。从技术上讲,环境是由 环境记录(Enviroment Record)(一个将标识符映射到值的实际存储表)以及对其外层环境的引用 (可能为 null)组成的。
③简而言之:环境是一种存储标识符到变量映射的结构。(这里,标识符指变量或者函数的名称,变量是 对实际对象(包括函数对象和数组对象)的引用或者基础类型值)。
(3)词法环境的三种组件:
⦿环境记录(Environment Record)
⦿ 对外层环境的引用
⦿ this 绑定
(4)词法环境的抽象表示:
第一阶段:
全局执行上下文 = {
词法环境: {
环境记录: {
Type: "Object",
// 标识符绑定在这里
},
outer: <null>,
this: <全局对象>
}
}
第二阶段:
函数执行上下文 = {
词法环境: {
环境记录: {
Type: "Declarative",
// 标识符绑定在这里
},
outer: <全局或者外层函数环境引用>,
this: <取决于函数的调用方式>
}
}
2.执行阶段
在本阶段 JS 引擎再次扫描代码,完成所有变量赋值, 最终执行代码。
二、解析示例代码的执行上下文
let a = 20;
const b = 30;
var c;
function multiply(e, f) {
var g = 20;
return e * f * g;
}
c = multiply(20, 30);
1.全局执行上下文(第一阶段)
(1)当代码运行时,JavaScript 引擎首先创建一个全局执行上下文来执行全局代码。
创建阶段期间,全局上下文就是:
(2)执行阶段,变量赋值完成。
执行阶段期间,全局执行上下文变成:
图像展示:
2.函数执行上下文(第二阶段)
(1)当遇到调用函数 multiply(20, 30) 时,就创建一个新的函数执行上下文来执行该函数代码。
创建阶段期间该函数执行上下文就是这样的:
(2)之后,该执行上下文进入执行阶段,也就是说,该函数内的变量赋值已经完成。
执行阶段期间,该函数执行上下文就变成:
图像展示:
3.程序结束
该函数执行完成后,返回值被存储在 c 中。于是,全局词法环境就被更新了。之后,全局代码完成执行,程序结束。