变量提升是javascript引擎在预编译阶段将var和function声明登记到变量对象的过程,不移动代码也不执行赋值;var声明提升后值为undefined,function声明整体提升可前置调用;同名时函数优先;let/const不提升,访问前处于暂时性死区报错。

变量提升在函数作用域中,不是“代码被物理移动”,而是 JavaScript 引擎在进入函数执行上下文前的预编译阶段,把 var 声明和 function 声明提前登记到当前作用域的变量对象(VO)里。这个过程只影响声明,不执行赋值或函数体运行。
函数内部的 var 声明:声明提前,值为 undefined
在函数体内用 var 声明的变量,其声明会被提升到函数体顶部,但赋值保留在原位置。访问未赋值前的变量,得到 undefined,而非报错。
-
function foo() { console.log(a); var a = 123; }→ 实际等效于:function foo() { var a; console.log(a); a = 123; } - 输出
undefined,因为a已声明但尚未赋值
函数声明:整个函数定义被提升,可立即调用
使用 function name() { ... } 语法声明的函数,不仅名字被提升,整个函数体也一同提升。因此可在声明前安全调用。
-
foo(); function foo() { console.log('ok'); }→ 正常执行,输出ok - 这是函数声明(Function Declaration),不是函数表达式(如
var foo = function() {...})
var 与 function 同名时:函数优先,变量声明被忽略
当函数声明和 var 变量同名时,函数声明先被提升并占据该标识符;随后的 var a 声明不会覆盖或重复注册,但后续的赋值会覆盖函数值。
-
console.log(a); function a() {} var a = 10;
→ 输出ƒ a() {}(函数被完整提升) -
console.log(a); var a = 10; function a() {}
→ 仍输出函数(函数提升优先级高于 var 声明) - 若写成
var a = 10; function a() {},最终a是10,因为赋值发生在执行阶段,覆盖了之前提升的函数
let/const 不参与提升:暂时性死区(TDZ)是关键区别
let 和 const 声明不会被提升到作用域顶部;它们虽有声明绑定,但在初始化前处于“暂时性死区”,任何访问都会抛出 ReferenceError。
-
console.log(b); let b = 20;→ 报错:ReferenceError: Cannot access 'b' before initialization - 这说明:提升行为仅适用于
var和函数声明,let/const的设计初衷就是避免提升带来的混淆
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











