函数提升优先于变量提升,函数声明整体提升至作用域顶部可提前调用,var 声明仅提升变量名、赋值保留原位,同名时函数先占位后被赋值覆盖,let/const 不提升且存在暂时性死区。

函数提升优先于变量提升,且都发生在作用域顶部,但函数声明会完整提升(包括函数体),而变量声明只提升 var 关键字部分,赋值保留在原位置。
函数声明先被整体提升
JS 引擎在预编译阶段,会先扫描并提升所有 function 声明——整个函数定义(名称 + 函数体)都会移到当前作用域最上方。这意味着你可以在声明前调用它,不会报错,也能正常执行。
-
例如:
foo(); function foo() { console.log('ok'); }→ 输出ok - 即使同名变量随后出现,函数声明仍优先进入作用域顶部
var 变量声明紧随其后,但仅提升声明
var 声明会被提升到同一作用域顶部,但仅限 var a; 这部分;赋值语句(如 a = 10)完全不动,仍在原处执行。
-
例如:
console.log(a); var a = 10;→ 输出undefined(声明已提升,但尚未赋值) - 若与同名函数声明冲突,
var a的声明会被忽略(因为函数已占位),但后续赋值仍会覆盖函数
同名时函数覆盖变量,赋值覆盖函数
当函数声明和 var 变量同名时,提升顺序决定了初始状态:函数先落位;但执行阶段的赋值操作,会把函数替换成新值。
立即学习“Java免费学习笔记(深入)”;
-
例如:
console.log(a); // 输出:ƒ a() {}(函数体) a(); // 正常执行 var a = 10; console.log(a); // 输出:10 - 关键点:不是“变量没提升”,而是它的声明被跳过;真正起作用的是后面的赋值
let/const 不参与提升,存在暂时性死区
let 和 const 声明不会被提升到作用域顶部,它们在声明前处于“暂时性死区”(TDZ)。访问会直接抛出 ReferenceError,而不是返回 undefined。
-
例如:
console.log(b); let b = 20;→ 报错:ReferenceError: Cannot access 'b' before initialization - 这和
var的行为有本质区别,也说明提升机制只适用于var和function声明


















