变量提升是JavaScript引擎在创建阶段将var和function声明提升至作用域顶部,但不提升赋值;let/const虽声明提升却不初始化,导致TDZ内访问报错。
变量提升(Hoisting)不是“代码被移动了”,而是 JavaScript 引擎在执行前的「创建阶段」把声明收集到作用域顶部的行为。关键在于:只提升 var 和 function 的声明,不提升赋值;而 let 和 const 虽然也“提升声明”,但不会初始化——这就引出了「暂时性死区」(TDZ)。
这是最常踩坑的地方:你以为没声明就不能用,结果它默默返回 undefined,还不会报错,导致逻辑出错却难定位。
console.log(a); // undefined(不报错) vara= 10;
var a; 提升到作用域顶部,初始值为 undefined
a = 10 仍留在原位置,执行时才发生if 块里、循环中都一样——只要在同一个函数作用域,就可提前读取let 变量在声明语句执行前处于「暂时性死区」(TDZ),任何读写操作都会触发 ReferenceError。这不是 bug,是设计来强制你写更安全代码的机制。
console.log(b); // ReferenceError: Cannot access 'b' before initialization letb= 20;
let b = ... 执行前触碰它for (let i...) 循环头部)很多线上 bug 来自对提升行为的误判
,尤其在条件分支、模块加载顺序、或与 typeof 配合时:
var 下的 typeof x 永远不会报错(返回 "undefined"),容易掩盖未定义问题let 下的 typeof x 在 TDZ 内直接报错,反而暴露了依赖顺序问题let 声明不会挂载到 window,而 var 会——跨脚本调试时变量“突然消失”往往源于此var 声明响应式数据,可能因提升导致初始化时机错乱;let 则让作用域和生命周期更可控真正要注意的不是“记住了区别”,而是:只要没显式写 var,就别假设变量能在声明前安全使用——哪怕它看起来“应该存在”。