调用栈
控制流经过函数的方式有点复杂。 让我们仔细看看它。 这是一个简单的程序,它执行了一些函数调用:
function greet(who) {console.log("Hello " + who);}greet("Harry");console.log("Bye");
这个程序的执行大致是这样的:对greet的调用使控制流跳转到该函数的开始(第 2 行)。 该函数调用控制台的console.log来完成它的工作,然后将控制流返回到第 2 行。 它到达greet函数的末尾,所以它返回到调用它的地方,这是第 4 行。 之后的一行再次调用console.log。 之后,程序结束。
我们可以使用下图表示出控制流:
not in functionin greetin console.login greetnot in functionin console.lognot in function
由于函数在返回时必须跳回调用它的地方,因此计算机必须记住调用发生处上下文。 在一种情况下,console.log完成后必须返回greet函数。 在另一种情况下,它返回到程序的结尾。
计算机存储此上下文的地方是调用栈。 每次调用函数时,当前上下文都存储在此栈的顶部。 当函数返回时,它会从栈中删除顶部上下文,并使用该上下文继续执行。
存储这个栈需要计算机内存中的空间。 当栈变得太大时,计算机将失败,并显示“栈空间不足”或“递归太多”等消息。 下面的代码通过向计算机提出一个非常困难的问题来说明这一点,这个问题会导致两个函数之间的无限的来回调用。 相反,如果计算机有无限的栈,它将会是无限的。 事实上,我们将耗尽空间,或者“把栈顶破”。
function chicken() {return egg();}function egg() {return chicken();}console.log(chicken() + " came first.");// → ??
