myfreax

JavaScript 调用栈

在本教程中,您将了解 JavaScript 调用栈,这是一种跟踪函数调用的机制

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(后进先出)原则工作。

内容导航