var在编译阶段提升至函数/全局顶部并初始化为undefined;let/const虽提升但不初始化,处于暂时性死区(TDZ),声明前访问报ReferenceError;const额外要求声明时必须赋值且绑定不可重赋。

识别 var、let 和 const 在 V8 引擎中的初始化与提升机制,关键不是“看代码是否报错”,而是理解 V8 编译阶段如何为不同声明创建执行上下文中的绑定,并在运行时如何处理访问请求。
var:声明与初始化分离,值默认为 undefined
V8 在编译阶段会把 var 声明提升到函数或全局作用域顶部,并在变量环境中为其分配空间,初始值设为 undefined。赋值操作保留在原位置,不提升。
- 声明前访问 → 返回
undefined(不报错) - 同一作用域重复声明 → 后者覆盖前者(无语法错误)
- 在函数内声明的 var,即使写在 if 块里,也属于整个函数作用域
let/const:声明提升但不初始化,进入暂时性死区(TDZ)
V8 仍会在词法环境(LexicalEnvironment)中为 let/const 预留绑定槽位,但不赋予初始值。从块作用域开始到声明语句执行前,该变量处于 TDZ —— 此时任何读写都会触发 ReferenceError。
- 声明前访问 → 报
ReferenceError: Cannot access 'x' before initialization - let/const 不允许在同一作用域重复声明(语法错误)
- for 循环中用 let 声明计数器,V8 为每次迭代创建独立绑定(非共享变量)
const 的额外约束:绑定不可重赋值
const 在 TDZ 行为上与 let 完全一致,区别仅在初始化之后:必须在声明时赋值,且后续不能重新赋值(即不能改变绑定指向的内存地址)。
-
const a;→ 语法错误(缺少初始化) -
const obj = {};→ 合法;obj.name = 'test';→ 合法(改内容不改绑定) -
obj = {};→ 报错(试图重新绑定)
快速验证方法(在 Chrome DevTools 或 Node.js 中运行)
直接测试三类声明在声明前的访问行为,是最直观的识别方式:
-
console.log(a); var a = 1;→ 输出undefined -
console.log(b); let b = 2;→ 报ReferenceError -
console.log(c); const c = 3;→ 报ReferenceError
这些表现正是 V8 执行上下文构建逻辑的外在反馈:var 走变量环境(VariableEnvironment),let/const 走词法环境(LexicalEnvironment),且后者在初始化前拒绝访问。

















