摘要: 本教程将介绍 JavaScript 调用栈,它是一种用于跟踪函数调用的机制。
JavaScript 调用栈简介
调用栈是 JavaScript 引擎用来跟踪其在调用多个函数的代码中的位置的一种方式。它包含有关当前正在运行的函数以及从该函数中调用的函数的信息……
此外,JavaScript 引擎使用调用栈来管理执行上下文
- 全局执行上下文
- 函数执行上下文
调用栈的工作原理基于后进先出 (LIFO) 原则。
执行脚本时,JavaScript 引擎会创建一个全局执行上下文并将其推入调用栈顶部。
每当调用一个函数时,JavaScript 引擎都会为该函数创建一个函数执行上下文,将其推入调用栈顶部,并开始执行该函数。
如果一个函数调用另一个函数,JavaScript 引擎将为被调用的函数创建一个新的函数执行上下文,并将其推入调用栈顶部。
当前函数完成后,JavaScript 引擎会将其从调用栈中弹出并恢复执行之前的状态。
当调用栈为空时,脚本将停止执行。
JavaScript 调用栈示例
让我们从以下示例开始
function add(a, b) {
return a + b;
}
function average(a, b) {
return add(a, b) / 2;
}
let x = average(10, 20);
Code language: JavaScript (javascript)
当 JavaScript 引擎执行此脚本时,它会将全局执行上下文 (用main()
或global()
函数表示) 放入调用栈。

全局执行上下文进入创建阶段,然后进入执行阶段。
JavaScript 引擎执行对average(10, 20)
函数的调用,并为average()
函数创建一个函数执行上下文,将其推入调用栈顶部。

JavaScript 引擎开始执行average()
,因为average()
函数位于调用栈顶部。
average()
函数调用add()
函数。此时,JavaScript 引擎为add()
函数创建一个新的函数执行上下文,并将其放置在调用栈顶部。

JavaScript 引擎执行add()
函数并将其从调用栈中弹出。

此时,average()
函数位于调用栈顶部,JavaScript 引擎执行并将其从调用栈中弹出。

现在,调用栈为空,因此脚本停止执行。

下图说明了所有步骤中调用栈的总体状态。

栈溢出
调用栈的大小是固定的,取决于宿主环境 (Web 浏览器或 Node.js) 的实现。
如果执行上下文的数量超过栈的大小,将会发生栈溢出错误。
例如,执行一个递归函数时,如果它没有退出条件,JavaScript 引擎将发出栈溢出错误。
function fn() {
fn();
}
fn(); // stack overflow
Code language: JavaScript (javascript)
异步 JavaScript
JavaScript 是一种单线程编程语言。这意味着 JavaScript 引擎只有一个调用栈。因此,它一次只能执行一个操作。
执行脚本时,JavaScript 引擎会从上到下、逐行执行代码。换句话说,它是同步的。
异步意味着 JavaScript 引擎可以在等待另一个任务完成时执行其他任务。例如,JavaScript 引擎可以
- 向远程服务器请求数据。
- 显示一个加载指示器
- 当数据可用时,将其显示在网页上。
为此,JavaScript 引擎使用事件循环,这将在下一教程中介绍。
总结
- JavaScript 引擎使用调用栈来管理执行上下文。
- 调用栈使用基于 LIFO (后进先出) 原则的栈数据结构。