函数声明一定先于var变量被提升,即预编译时先完整提升function foo(){},再处理var bar;同名时函数胜出,var声明被忽略,仅赋值语句覆盖函数。

函数声明一定先于 var 变量被提升
JavaScript 引擎在预编译阶段会按固定顺序处理声明:先扫描并提升所有 函数声明(function foo() {}),再处理 var 变量声明(var bar)。这意味着即使函数声明写在 var 语句之后,它也会“出现在”变量声明之前。
例如:
console.log(a); // 输出:function a() { console.log(10); }
var a = 10;
function a() { console.log(10); }
实际等效于:
function a() { console.log(10); } // 函数先完整提升
var a; // var 声明被忽略(因 a 已存在)
console.log(a); // 此时 a 还是函数
a = 10; // 赋值才覆盖函数
同名时函数声明胜出,var 声明不生效
当函数声明与 var 声明使用相同标识符(如都叫 a),引擎不会报错,也不会覆盖函数——而是直接跳过该 var 声明。只有后续的赋值语句(a = 10)才会真正改变值。
- 声明前访问:得到函数本身(可调用)
- 赋值后访问:得到新值(函数被覆盖,不再可调用)
- var 声明本身不产生效果,因为函数已占据该绑定
函数表达式不享受“函数提升”,只走变量提升规则
像 var fn = function() {} 或 const fn = () => {} 这类写法,本质是“给变量赋值”,不是函数声明。它们只遵循对应关键字的提升逻辑:
-
var fn→ 提升为var fn;,初始值undefined -
fn()在赋值前调用 → 报TypeError: fn is not a function -
let/const fn→ 声明被提升但不可访问(暂时性死区),提前读取直接ReferenceError
看代码时可快速判断提升顺序的两个信号
遇到含混代码,抓住这两个关键点就能理清执行流:
-
有没有
function 标识符() { ... }的完整语法?有 → 整个函数体被提前 -
标识符是否出现在
var后面、且右边不是函数字面量?是 → 仅声明提升,值仍为undefined直到执行到赋值行
不需要背规则,只要记住:函数声明是“带身体搬家”,var 声明是“空壳占位”,而赋值永远留在原地执行。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











