变量环境和词法环境是执行上下文的两个独立组件:前者处理var和函数声明,创建时初始化并支持变量提升;后者管理let/const及块级作用域,动态更新并支持作用域链与闭包。

变量环境和词法环境是执行上下文内部的两个独立组件,它们分工明确、协同工作,共同支撑 JavaScript 的作用域行为和变量生命周期。
变量环境:负责 var 和函数声明的“初稿”
变量环境在执行上下文创建阶段就完成初始化,主要登记 var 声明的变量(初始值为 undefined)和 函数声明(直接绑定完整函数体)。它的特点是静态、粗粒度,不随代码块进入/退出而变化。
- var 声明会被提升并初始化,因此可以在声明前访问(输出
undefined) - 函数声明也会被整体提升,调用位置不受限制
- 它只支持函数作用域,没有块级概念
- 全局环境下,var 声明会自动挂载到全局对象(如
window)上
词法环境:管理 let/const 和块级作用域的“精细账本”
词法环境在创建阶段初始化为变量环境的副本,但执行阶段会动态更新,专门追踪 let/const 声明、函数参数,以及 块级作用域结构。它通过外部环境引用(outer reference)链接父级词法环境,构成作用域链。
- let/const 声明虽被提升,但不初始化,访问会触发“暂时性死区”(TDZ)报错
- 每次进入
{}、if、for等块,都会创建新词法环境,并设置其 outer 指向当前词法环境 - 块执行结束,该词法环境即失效(不销毁内存,但不再参与标识符查找)
- 闭包的本质,就是内层函数的词法环境持续持有对外层词法环境的 outer 引用
两者的关系与关键差异
变量环境和词法环境不是替代关系,而是共存互补:变量环境处理历史遗留的 var 行为,词法环境承载现代 ES6+ 的作用域语义。它们都存在于同一个执行上下文中,但在不同阶段承担不同职责。
立即学习“Java免费学习笔记(深入)”;
- 创建阶段:词法环境初始等于变量环境;执行阶段开始后,二者各自独立更新
- 查找变量时,引擎优先在当前词法环境的记录器中找;找不到则沿 outer 引用向上查找(即作用域链)
- 函数声明同时存在于两个环境中(为兼容性),但 let/const 只属于词法环境
- 严格模式下,eval 内部的变量环境和词法环境相互隔离,避免污染外层
理解它们的关键,在于把“执行上下文”看作一个容器,而变量环境和词法环境是这个容器里两本不同的登记册——一本记老规矩,一本记新规则,一起决定你写的每个变量到底在哪能用、什么时候能用、用的是谁。


















