变量提升指JavaScript引擎在编译阶段将var声明和函数声明提升至作用域顶部,但var只提升声明不提升赋值,函数声明则完全提升;let/const虽被提升但受暂时性死区限制,访问会报ReferenceError。

JavaScript中的变量提升(Hoisting)是指变量和函数声明在代码执行前被“移动”到其所在作用域顶部的现象。它不是字面意义上的物理移动,而是JavaScript引擎在编译阶段将声明部分提前处理的结果。理解它对避免意外的undefined、ReferenceError或逻辑错误至关重要。
变量提升只提升声明,不提升赋值
使用var声明的变量会被提升,但初始化(赋值)保留在原位置。这意味着你可以在声明前访问该变量,得到undefined,而不是报错。
例如:
console.log(a); // undefined
var a = 10;
console.log(a); // 10
实际等价于:
立即学习“Java免费学习笔记(深入)”;
var a;
console.log(a); // undefined
a = 10;
console.log(a); // 10
-
注意:只有
var有这种“声明+初始化分离”的提升行为 -
let和const也会被提升,但它们处于“暂时性死区”(TDZ),在声明前访问会直接抛出ReferenceError
函数声明会被完全提升,函数表达式则不会
函数声明(function foo() {...})不仅声明被提升,整个函数体也一同提升,因此可在定义前调用。
foo(); // 正常输出 "hello"
function foo() {
console.log("hello");
}
但函数表达式(如用var、let或const赋值的函数)只提升变量名,不提升赋值,因此调用会出错:
bar(); // TypeError: bar is not a function(var情况)或 ReferenceError(let/const)
var bar = function() { console.log("world"); };
- 函数声明优先级高于
var变量声明,同名时函数声明会覆盖变量声明 - 箭头函数属于函数表达式,同样不被完全提升
let/const 的提升与暂时性死区(TDZ)
let和const声明确实被提升,但在声明语句执行前,它们所绑定的标识符不可访问——这段区域就是暂时性死区。
console.log(b); // ReferenceError
let b = 20;
- TDZ从块级作用域开头开始,到声明语句执行完成为止
- typeof对TDZ中的变量也不安全:
typeof b同样抛错,不同于var下的"undefined" - 这有助于尽早发现未声明就使用的错误,增强代码健壮性
如何规避变量提升带来的问题
现代开发中,推荐通过以下方式减少相关陷阱:
- 始终在作用域顶部声明变量(尤其是
var),养成“先声明后使用”的习惯 - 优先使用
const和let替代var,利用TDZ获得更早的错误提示 - 函数尽量使用函数声明(需被提前调用时),或确保函数表达式在调用前已赋值
- 启用ESLint规则如
no-use-before-define,自动检测潜在的提前使用问题










