函数声明会被完整提升至作用域顶部,包括函数名和函数体,故可前置调用;而函数表达式仅变量声明可能提升(var),赋值不提升;同名时函数声明优先于var变量;块级函数声明在严格模式下具块级作用域且存在tdz。

函数声明的变量提升,核心是“整个函数定义被提前到作用域顶部”,不是只提名字,而是连同函数体一起可用。这和变量提升(只提声明、不提赋值)有本质区别。
函数声明会被完整提升
函数声明(function name() { ... })在编译阶段就被整体提升到当前作用域最上方,包括函数名和函数体。因此可以在声明前调用:
sayHi(); // 正常输出 "Hi!"function sayHi() { console.log("Hi!"); }
引擎实际执行时,等价于先注册了完整的 sayHi 函数,再执行调用语句。
函数表达式不会被提升
用 var/let/const 赋值函数(如 var fn = function() {} 或 const fn = () => {})属于赋值操作,只有变量声明部分可能提升(仅 var),函数本身不提升:
fn(); // TypeError: fn is not a function(var 情况)var fn = function() { console.log("I'm expression"); };fn(); // 正常执行
这是因为 var fn 声明被提升并初始化为 undefined,但赋值(即函数创建)仍留在原位置。
同名声明时,函数声明优先级更高
当函数声明与 var 变量声明同名,函数声明会覆盖变量声明(在提升阶段完成):
test(); // 输出 "function"function test() { console.log("function"); }var test = 123;
注意:后续的 test = 123 是赋值操作,会把函数替换成数字,但调用发生在赋值前,所以仍能执行函数。
块级作用域中函数声明行为需谨慎
ES6 严格模式下,在 if、for 等块中声明函数,被视为块级绑定,类似 let:
- 不会提升到外层函数或全局作用域
- 在块外访问会报
ReferenceError - 在块内声明前访问也会进入暂时性死区(TDZ)
例如:if (true) { function foo() {} } foo(); // ReferenceError(严格模式)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











