JavaScript 调用栈
在本教程中,您将了解 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);
当 JavaScript 引擎执行此脚本时,它会放置将全局执行上下文函数在调用栈上,由 main()
表示。
全局执行上下文进入创建阶段并进入执行阶段。
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
异步JavaScript
JavaScript 是一种单线程编程语言。这意味着 JavaScript 引擎只有一个调用栈。因此,它一次只能做一件事。执行脚本时,JavaScript 引擎从上到下逐行执行代码。换句话说,它是同步的。
异步意味着 JavaScript 引擎可以在不等待另一个任务完成,同时执行其他任务。例如,JavaScript 引擎可以:
从远程服务器请求数据。
展示载入动画
当数据可用时,将其显示在网页上。
因此,JavaScript 引擎使用事件循环,这将在以下教程中介绍。
结论
JavaScript 引擎使用调用栈来管理执行上下文。调用栈基于 LIFO(后进先出)原则工作。
如果你有任何疑问,欢迎您的反馈和建议。点击下方阅读原文获取更好排版格式与文章参考引用。