JS如何知道在哪里继续调用堆栈?



我想了解每个函数弹出后调用堆栈是如何工作的。

例如:

function inner() {
console.log("what happens after inner() is popped from Call Stack?");
}
function outer() {
inner();
console.log("how does Call Stack return to this line?");
}
outer();

我可以告诉outer()是第一个被推到调用堆栈的东西:

TOP of Call Stack
----------------
outer() // not executed. so let's begin at line 1!
----------------
BOTTOM of Call Stack

现在,当我们到达outer()的第一行inner()时,前者被推入调用堆栈,所以我们有:

TOP of Call Stack
----------------
inner() // not executed yet!
outer() // line 1 is on… 
----------------
BOTTOM of Call Stack

inner()中的console.log被执行时,inner()结束并从调用堆栈中弹出,所以我们有:

TOP of Call Stack
----------------
outer() // line 1 is executed. let's continue with line 2! 
----------------
BOTTOM of Call Stack

但是调用栈怎么知道从哪里继续当它回到outer()?如何outer()在堆栈的顶部不重新开始在第一行?它是否有任何内存或数据结构,如指针(指向外部函数行)?如果有,它在哪里?如果一个函数被递归100次,这意味着我们有100个堆栈项,JS如何能够管理所有的位置并知道从哪里继续?

调用堆栈不仅存储要返回的函数,还存储该函数中的特定位置。

还将局部变量的值存储在函数中。这对于使递归函数正常工作至关重要。

请注意,所有这些都是JavaScript VM的实现细节,可以通过各种方式实现。例如,返回位置可以是将JavaScript jit编译为机器码后的内存地址。或者函数可以内联,根本不留下堆栈帧。

调用堆栈是解释器(如web浏览器中的JavaScript解释器)的一种机制,用于跟踪其在调用多个函数的脚本中的位置-当前正在运行的函数以及从该函数中调用的函数等。

当脚本调用函数时,解释器将其添加到调用堆栈中,然后开始执行该函数。由该函数调用的任何函数都被添加到调用堆栈中,并在到达其调用的地方运行。当当前函数完成时,解释器将其从堆栈中取出,并在上次代码清单中停止的地方继续执行。如果堆栈占用的空间大于分配给它的空间,则"堆栈溢出";抛出错误。

function greeting() {
// [1] Some code here
sayHi();
// [2] Some code here
}
function sayHi() {
return "Hi!";
}
// Invoke the `greeting` function
greeting();
// [3] Some code here

最新更新