JavaScript - 调用堆栈



JavaScript 引擎使用调用堆栈来管理执行上下文。它是 JavaScript 运行引擎跟踪 JavaScript 代码中的函数调用的重要机制。但是,JavaScript 调用堆栈的工作是在内部执行的,但了解 JavaScript 如何执行函数非常重要。

JavaScript 调用堆栈跟踪当前需要运行的函数或代码块。它以 LIFO (后进先出) 方式工作。因此,无论在调用堆栈的顶部添加什么函数,它都会首先执行。

JavaScript 调用堆栈如何工作?

每当执行任何 JavaScript 代码时,它都会将全局执行上下文添加到脚本中。

当您调用任何函数时,JavaScript 引擎会将该函数添加到调用堆栈中。之后,当您从外部函数调用任何嵌套函数时,它会在调用堆栈中添加一个嵌套函数。

当内部函数的执行完成时,它会从调用堆栈中弹出该函数。接下来,它执行外部函数并将其从调用堆栈中弹出。同样,它开始在全局上下文中执行代码。

当调用堆栈为空时,脚本将停止运行。

让我们通过示例来了解 JavaScript 调用堆栈。


function two() {
	 console.log("this is function two");
}

function one() {
	 two();
	 console.log("This is function one");
}

one();

上面的代码将像这样执行。

  • 1. 当代码开始执行时,调用堆栈将保持为空,直到执行到达 one() 函数。
  • 2. 在调用堆栈中添加函数 one()。现在,调用堆栈是 [one()]。
  • 3. 执行函数 one() 的第一行,该函数调用函数 two()。
  • 4. 在调用堆栈中添加函数 two()。现在,调用堆栈是 [two(), one()]。
  • 5. 执行函数 two() 的所有行。
  • 6. 向后移动以执行函数 one() 的剩余代码行。
  • 7. 从调用堆栈中删除函数 two()。现在,调用堆栈是 [one()]。
  • 8. 开始执行函数 one() 的剩余代码。当函数 one() 的执行完成后,JavaScript 引擎开始执行剩余的代码。
  • 9. 从调用堆栈中删除函数 one()。现在,调用堆栈为空。
  • 10. 执行剩余的代码。

每当我们执行下面的代码时,它都会在调用堆栈中添加全局执行上下文。每当它从全局执行竞赛中调用任何函数时,它都会将该函数添加到调用堆栈中,并首先开始执行该函数。

当从特定函数调用另一个函数时,该函数将被添加到调用堆栈并获得执行优先级。

当特定函数的执行完成后,解释器会将其从调用堆栈中删除。

每当堆栈占用的空间超过其大小时,它就会引发 'stack overflow' 错误。


<html>
<body>
	 	<h2> JavaScript - Call stack </h2>
	 	<div id = "output"></div>
	 	<script>

	 	 const output = document.getElementById("output");
	 	 function two() {
	 	 	 	 output.innerHTML += "two <br>";
	 	 }

	 	 function one() {
	 	 	 	 two();
	 	 	 	 output.innerHTML += "one <br>";
	 	 }

	 	 one();
</script>
</body>
</html>

JavaScript 调用堆栈溢出

每当调用堆栈的大小超过定义的大小时,就会发生调用堆栈溢出。通常,每当递归函数没有出口点调用时,就会发生堆栈溢出。

例如,在下面的代码中,fib() 函数没有出口点。因此,它会引发调用堆栈溢出错误。


function fib() {
	 	fib();
}
fib();

Javascript 是一种单线程编程语言。因此,它从上到下逐行运行代码。这意味着 JavaScript 程序只能有 1 个调用堆栈,并且一次可以执行一行。