Skip to content

执行上下文和执行栈是什么? ​

执行上下文是一次代码运行时的环境,里面有变量环境、词法环境和 this。执行栈是这些上下文叠起来的调用栈。函数调用就压栈,返回就出栈。

原理 ​

全局代码一开始就有全局上下文。每调用一个函数,创建一个函数上下文。栈顶是正在运行的那段代码。

创建一个上下文时,引擎先处理声明:var 和函数声明会进变量环境,var 初值是 undefined,函数声明可以直接用。let 和 const 进词法环境,初始化前处于暂时性死区。然后才逐行执行。

箭头函数不创建自己的 this,它的上下文仍会入栈,但 this 沿外层词法环境找。

执行完的上下文出栈后,如果有闭包还握着它的环境,变量对象不会马上回收。见 作用域与闭包。

追问 ​

和作用域是一回事吗?

不是。作用域是写代码时就确定的访问范围。执行上下文是运行到那一次调用时创建的。同一个函数调用两次,有两个执行上下文,作用域规则只有一套。

栈溢出怎么来的?

递归没有终止,上下文一直压栈。尾调用在严格模式且满足条件时可以被引擎复用栈帧,见 尾递归。

易错点 ​

  • 函数声明整体提升,函数表达式的变量名按 var 或 let 的规则提升,函数体不会提前可用。
  • 执行栈描述的是同步调用。then 和 setTimeout 的回调是以后新的一次入栈,不是留在当前栈里。
  • 块级 let 会单独有词法环境,不等于整个函数只有一个变量对象。

相关 ​