函数执行上下文在被调用的瞬间创建,经历创建→执行→销毁三阶段;创建时初始化环境、绑定this占位、构建作用域链;执行时赋值变量、绑定this、运行代码;销毁时通常释放内存,但闭包会因外部引用保留词法环境。

函数执行上下文不是“一调用就立刻执行完”,而是严格按创建 → 执行 → 销毁三步走,每一步都决定变量能否访问、this指向谁、作用域链怎么查。关键不在“有没有”,而在“什么时候发生”。
函数执行上下文何时被创建?
只在函数**被调用的瞬间**创建,不是定义时,也不是进入作用域时。
- 哪怕函数写在全局最底下,只要没被调用,就不会生成对应上下文
- 每次调用都新建一个独立上下文(递归调用会生成多个并存的上下文)
- 箭头函数没有自己的执行上下文——它直接沿用外层函数的上下文
创建阶段到底做了什么?
这是真正埋下“变量提升”“函数优先”“暂时性死区”等现象根源的阶段,代码一行未执行,但内存已分配、结构已搭好。
- 生成arguments对象(仅普通函数,箭头函数无)
- 初始化词法环境(Lexical Environment):注册函数声明(直接赋值)、let/const声明(仅注册,不赋值,进TDZ)、形参(绑定传入值)
- 初始化变量环境(Variable Environment):处理
var声明(注册 + 默认赋值为undefined) - 确定this值:此时只是预留位置,实际绑定要到执行阶段才根据调用方式落实
- 构建作用域链:基于函数定义时的位置,把当前词法环境 + 所有外层词法环境串联起来
执行阶段发生了什么变化?
从“准备就绪”进入“真实运行”,变量开始赋值,表达式求值,语句逐行执行。
-
var a = 10:此时才真正把10写入变量环境中的a -
let b = 20:跳过TDZ后,把20写入词法环境中的b -
this完成最终绑定:比如obj.fn()中this指向obj,fn()独立调用则指向window或undefined(严格模式) - 遇到
return或自然结束,立即触发销毁流程
销毁阶段:什么时候消失?为什么有时不消失?
函数执行完毕后,其执行上下文本应立即出栈、释放内存。但有一个例外:
- 正常情况:上下文弹出执行栈,内部变量对象、词法环境全部回收
- 闭包场景:若内部函数被外部引用(如返回了内层函数),该函数会保留对外层词法环境的引用,导致外层上下文无法被回收——这就是闭包延长生命周期的本质
- 注意:不是“上下文还活着”,而是它的词法环境被其他活跃上下文持有了引用











