JavaScript提升是引擎在编译阶段将var和function声明的声明部分提前注册到作用域,但赋值仍保留在原位置;var声明被初始化为undefined,let/const存在暂时性死区,函数声明完全提升而函数表达式仅变量名提升。
提升不是代码被“移动”到顶部,而是 JavaScript 引擎在编译阶段把 var 声明和 function 声明的**声明部分**提前注册到当前作用域中,但赋值或初始化仍保留在原位置。这意味着你可以在声明前访问变量或调用函数,但结果可能出乎意料。
var 声明的提升行为var 只提升声明,不提升赋值,且会被初始化为 undefined。这是最常踩坑的地方。
console.log(a); var a = 1;,输出是 undefined,不是报错console.log(b); let b = 2;,直接抛出 ReferenceError —— let 和 const 不提升声明(严格来说是存在「暂时性死区」)var a = 1; var a = 2; 不报错,等价于一次声明 + 两次赋值console.log(x); // undefined var x= 10; console.log(x); // 10
function 声明 vs function 表达式只有使用 function 关键字开头的**函数声明**才会被完全提升(声明 + 函数体);而函数表达式(如赋值给 var / const)只提升变量名,不提升函数体。
foo(); function foo() { ... } ✅ 正常执行bar(); var bar = function() { ... }; ❌ 报 TypeError: bar is not a function(因为 bar 是 undefined)baz(); const baz = () => {}; ❌ 直接 ReferenceError
hoistedFunc(); // OK: "I'm hoisted"
function hoistedFunc() {
console.log("I'm hoisted");
}
notHoistedFunc(); // TypeError: notHoistedFunc is not a function
var notHoistedFunc = function() {
console.log("I'm NOT hoisted");
};
提升机制容易掩盖逻辑顺序问题,现代代码应尽量规避依赖它。
if、for)里用 var
const / let 替代 var,它们不参与传统提升,行为更可预测if 内赋值给 const 变量)import 和 export 也存在提升,但必须出现在顶层,不能在条件或函数内var 声明看起来像“全局可见”,却在赋值前返回 undefined——这个中间态最容易被忽略。