JavaScript编程精解(原书第3版)
上QQ阅读APP看书,第一时间看更新

3.6 调用栈

控制流经函数的方式有些复杂。让我们仔细地看看。这是一个简单的程序,它可以进行一些函数调用:

贯穿这个程序的过程大致如下:对greet的调用导致控制跳转到此函数的开头(第2行)。此函数调用console.log,让它接受控制,完成其工作,然后将控制返回到第2行。在此它到达了greet函数的末尾,因此它返回到调用它的位置,即第4行。之后再次调用console.log。之后返回,程序到达终点。

我们可以像这样显示控制流程:

因为函数返回时必须跳回到调用它的位置,所以计算机必须记住调用发生的上下文。在第一种情况下,console.log必须在完成后返回greet函数。在另一种情况下,它返回到程序的末尾。

计算机存储此上下文的位置是调用栈。每次调用函数时,当前上下文都存储在此栈的顶部。当函数返回时,它会从栈中删除顶层上下文并使用此上下文继续执行。

存储此栈需要计算机内存中的空间。当栈变得太大时,计算机将失败并显示“栈空间不足”或“递归过多”等消息。以下代码通过向计算机询问一个会导致在两个函数之间无限来回的非常难的问题先有鸡还是先有蛋。——译者注来说明这一点。相反,如果计算机具有无限的栈,它将是无限的。事实上,我们将耗尽空间或“吹爆栈”。