函数调用栈
函数体
函数声明或函数表达式,都能够创建一个函数体。函数体也是数据,在代码解析阶段,被持久的存在于堆内存中。
执行上下文
执行函数会创建执行上下文,执行上下文会占用新的内存空间。执行上下文会按函数体内编辑好的代码逻辑,实时的记录函数体在执行过程中的所有状态与数据。
JS 的运行环境:
- 全局环境:代码运行时首先会进入全局环境,生成全局上下文
- 函数环境:当函数被调用时,进入函数环境执行代码,同时执行上下文被创建
当调用一个新函数时,新的执行上下文就会被创建。JS 引擎使用栈的方式来跟踪多个执行上下文的运行情况,我们称之为「函数调用栈」。正在执行的函数永远处于栈顶,栈顶上下文执行完毕就会出栈,被垃圾回收器回收,新的栈顶上下文继续执行。
1 | var color = 'blue'; |
- 进入全局上下文,并一直处于栈底
- 遇到
changeColor()
,创建 changeColor 上下文,新的上下文入栈并开始执行,此时全局上下文被挂起 - 遇到
swapColors()
,创建 swapColors 上下文,新的上下文入栈并开始执行,changeColor 上下文被挂起 - swapColors 代码执行完毕,swapColors 上下文出栈,等待被回收
- changeColor 上下文激活,changeColor 代码执行完毕,changeColor 上下文出栈,等待被回收
- 全局上下文被激活,所有代码执行完毕,全局上下文出栈,函数调用栈被清空
console.trace()
我们可以使用 console 的 trace 方法打印出,当前函数调用栈中有哪些函数
当我们代码报错时,浏览器的 console 面板也会把当前函数调用栈打印出来,这是我们定位 bug 的有效手段