JavaScript提升是引擎在编译阶段将var和function声明的声明部分提前注册到作用域,但赋值仍保留在原位置;var声明被初始化为undefined,let/const存在暂时性死区,函数声明完全提升而函数表达式仅变量名提升。

JavaScript 提升(Hoisting)到底是什么
提升不是代码被“移动”到顶部,而是 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");
};
实际开发中该注意什么
提升机制容易掩盖逻辑顺序问题,现代代码应尽量规避依赖它。
立即学习“Java免费学习笔记(深入)”;
- 始终在使用前声明变量,尤其避免在块级作用域(
if、for)里用var - 优先用
const/let替代var,它们不参与传统提升,行为更可预测 - 函数尽量统一用声明形式(若需条件定义,改用
if内赋值给const变量) - ES6 模块中,
import和export也存在提升,但必须出现在顶层,不能在条件或函数内
var 声明看起来像“全局可见”,却在赋值前返回 undefined——这个中间态最容易被忽略。











