说一说 JS 执行上下文和执行栈
执行上下文
shell
# 执行上下文是什么
执行上下文是 JavaScript 代码被解析和执行时所在环境
# 执行上下文的类型
全局执行上下文:只有一个,浏览器中是 window,Node.js 中是 global(默认的基础上下文)
函数执行上下文:每次调用函数时创建,可以有无数个(每次调用函数时创建)
eval 执行上下文:在 eval 函数中执行的代码拓展
shell
# 执行上下文生命周期
创建阶段:函数被调用但未执行代码,主做三件事:this 绑定、绑定词法环境、绑定变量环境
执行阶段:变量赋值
回收阶段:执行上下文出栈,等待回收
# 词法环境
环境记录(Environment Record)- 存储变量和函数声明
外部环境引用(Outer Environment Reference)- 指向外部词法环境
# 变量环境
变量环境是词法环境的一种特殊形式,主要用于处理 var 声明的变量和函数声明。
# 变量环境区别 和 词法环境
变量环境:存储 var 变量和函数声明,函数作用域、变量提升、函数级作用域共享
词法环境:存储 let、const、class 等,块级作用域、暂时性死区、每个块级作用域创建新环境执行栈
shell
# 执行栈是什么
执行栈(也叫调用栈)是一种后进先出(LIFO)的数据结构,用于存储代码执行期间创建的所有执行上下文。
# 执行栈的过程
入栈阶段:JS 代码执行开始 --- 每执行一个函数便会创建一个函数执行上下文 --- 并将其压入到执行栈中
出栈阶段:入栈完毕后开始出栈 --- 按照后进先出的顺序执行,也就先执行函数内部的函数,最后在执行外部函数
# 示例
function multiply(a, b) {
return a * b; // ③ 计算并返回结果
}
function square(n) {
return multiply(n, n); // ② 调用 multiply
}
function printSquare(x) {
const result = square(x); // ① 调用 square
console.log(result);
}
printSquare(5); // 开始执行
执行过程:
步骤 1: 入栈 [printSquare]
步骤 2: 入栈 [printSquare, square]
步骤 3: 入栈 [printSquare, square, multiply]
步骤 4: multiply 执行完毕,出栈
步骤 5: square 执行完毕,出栈
步骤 6: printSquare 执行完毕,出栈