变量提升发生在函数作用域内,var声明和function声明被提升至顶部,前者初始化为undefined,后者包括函数体;let/const仅声明提升但不初始化,触发tdz;函数声明优先于var声明。

JavaScript中变量提升(Hoisting)在函数作用域内发生,是因为引擎在执行代码前会先进行“预解析”(也叫编译阶段),把函数内部用 var 声明的变量和 function 声明提升到当前函数作用域顶部。注意:只有声明被提升,赋值不会。
var 声明的变量会被提升并初始化为 undefined
在函数体内使用 var 声明变量时,JS 引擎会在函数执行前把该声明“挪到”函数开头,并自动赋初始值 undefined。这意味着你可以在声明语句之前访问它,但值是 undefined,而不是报错。
- 例如:console.log(a); // undefined,接着 var a = 123; —— 不会报错,因为 var a; 已被提前处理
- 这种行为只适用于 var,let 和 const 虽然也会被提升,但不初始化,访问会触发暂时性死区(TDZ)错误
function 声明会被完全提升(包括函数体)
使用 function 关键字声明的函数(非函数表达式) 会被完整地提升到函数作用域顶部,包括函数名和函数体。因此可以在声明前调用它。
- 例如:foo(); // 正常输出 "hello",然后才是 function foo() { console.log("hello"); }
- 但如果是 const bar = function() {}; 或 var bar = function() {};,就只提升变量声明(bar 变量),不提升赋值,调用会报 TypeError(因为此时 bar 是 undefined)
提升发生在函数作用域内部,与块级作用域无关
即使 var 声明写在 if、for 等块中,它仍属于整个外层函数作用域,提升也针对整个函数。ES6 的 let/const 则不同,它们有块级作用域,且不参与传统意义上的“提升”。
- if (false) { var x = 1; } —— x 依然会被提升到函数顶部,只是赋值没执行
- console.log(x); // undefined,证明提升已发生,但未赋值
提升顺序:函数声明 > 变量声明
当函数名和变量名冲突时,函数声明优先于 var 声明被提升。如果两者同名,函数声明会覆盖变量声明(但不会覆盖后续的赋值)。
- 例如:console.log(fn); // function fn(){},接着是 var fn = 123; 和 function fn(){} —— 函数声明先被提升并生效
- 但执行到 var fn = 123; 后,fn 就被重新赋值为数字,原函数被覆盖
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











