调用栈是解释器(就像浏览器中的javascript解释器)追踪函数执行流的一种机制。当执行环境中调用了多个函数时,通过这种机制,能够帮助我们追踪到哪个函数正在执行,执行的函数体中又调用了哪个函数。
有关调用栈,你需要知道以下几点:
-
每调用一个函数,解释器就会把该函数添加进调用栈并开始执行。
-
正在调用栈中执行的函数还调用了其它函数,那么新函数也将被添加进调用栈,一旦这个函数被调用,便会立即执行。
-
当前函数执行完毕后,解释器将其清出调用栈,继续执行当前执行环境下的剩余的代码。
-
当分配的调用栈空间被占满时,会引发“堆栈溢出”。
举例
function greeting() {
// [1] 这里有代码哦~
sayHi();
// [2] 这里也有代码哦~
}
function sayHi() {
return "Hi!";
}
// 调用greeting函数
greeting();
// [3] 这里还有代码哦~
以上代码会按照如下方式运行:
-
忽略前面所有函数,直到
greeting()函数被调用。 -
把
greeting()添加进调用栈列表。
| 调用栈列表 |
|---|
| greeting() |
-
执行
greeting()函数体中的所有代码。 -
代码执行到
sayHi()时,该函数被调用 -
把
sayHi()添加进调用栈列表
| 调用栈列表 |
|---|
| greeting() |
| sayHI() |
-
执行
sayHi()函数体中的代码,直到全部执行完毕。 -
返回来继续执行
greeting()函数体中sayHi()后面的代码。 -
删除调用栈列表中的
sayHi()函数。
| 调用栈列表 |
|---|
| greeting() |
-
当
greeting()函数体中的代码全部执行完毕,返回到激活greeting()的代码行,继续执行剩余JS代码。 -
删除调用栈列表中的
greeting()函数。
| 调用栈列表 |
|---|
| 空 |
一开始,我们得到一个空空如也的调用栈。
随后,每当有函数被调用都会自动地添加进调用栈,执行完函数体中的代码后,调用栈又会自动地移除这个函数。
最后,我们又得到了一个空空如也的调用栈。