函数执行上下文在函数被调用的瞬间、执行任何代码前,由JS引擎同步完成创建、初始化绑定和执行三阶段:创建阶段建立词法/变量环境并确定this;初始化阶段为var/let/const赋初始值;执行阶段逐行运行代码。

函数执行上下文的创建过程不是运行时“开始执行”才启动的,而是在函数被调用的**瞬间、执行任何代码前**,由 JS 引擎同步完成的一套严格步骤。它决定了该次调用中变量怎么找、this 是什么、作用域链如何形成——理解这个过程,才能真正看懂闭包、this 绑定和 let/const 的报错时机。
创建阶段:三件事同步完成(不执行语句)
引擎在压入函数上下文前,先做三件初始化工作:
- 建立词法环境(LexicalEnvironment):记录形参、let/const 声明(值为 uninitialized)、内部 function 声明(函数对象直接绑定);同时设置 外部环境引用 —— 指向该函数定义时所在的词法环境(不是调用时!),这是闭包的底层基础
- 建立变量环境(VariableEnvironment):专门处理 var 声明(初始化为 undefined),也包含函数声明(与词法环境重复,历史兼容)
- 确定 this 值:此时不执行函数体,但 this 已根据调用方式锁定——普通调用是 undefined(严格模式)或全局对象(非严格),new 调用指向新实例,call/apply/bind 由传入值决定
初始化绑定:让声明真正“就位”
这一步紧接创建阶段,逻辑上属于创建流程的收尾:
- var a = 10 → 变量环境中 a 从 undefined 更新为 10
- let b = 20 或 const c = 30 → 词法环境中 b/c 从 uninitialized 状态设为对应值
- function foo() {} → 函数已在创建阶段绑定,此处不重复赋值
- const d = getValue() → getValue() 此时仍不调用,只完成绑定动作;实际求值发生在执行阶段
执行阶段:代码逐行运行,环境开始“活起来”
创建和初始化完成后,引擎才开始执行函数体内的语句:
立即学习“Java免费学习笔记(深入)”;
- 遇到 var 重新赋值(如 a = 42),直接修改变量环境中的值
- 遇到 let/const 赋值(如 b = 50),更新词法环境记录
- 每次嵌套函数调用,都会触发新一轮完整的三阶段流程(新上下文入栈)
- 若函数内有 let/const 声明,访问它们前必须已过初始化语句,否则抛出 ReferenceError(暂时性死区)
关键细节:为什么容易出错
这些行为背后有明确机制,不是“随机报错”:
- 作用域链在创建阶段就固定:函数在哪里定义,它的外部环境就指向哪里——和调用位置无关
- this 不是定义时决定的,但也不是执行到某一行才算;它在函数被调用的那一刻,由调用语法即时确定
- var 和 function 在创建阶段就“可用”(提升);let/const 虽被注册,但直到初始化语句执行前都不可访问
- 每次调用都新建上下文:参数、let 变量、this 都是独立的,递归调用会生成多个并存的函数上下文


















