函数声明会将函数名和整个函数体在编译阶段提升至作用域顶部,因此可先调用后声明;而函数表达式仅提升变量名,函数体需执行阶段赋值后才可用。

JavaScript 中函数声明的函数体,会在代码执行前被完整提升到当前作用域顶部,这个过程发生在“编译阶段”(也称预编译或预解析阶段),不是运行时才加载。
函数体整体提升是核心特征
与变量声明仅提升名字不同,函数声明(function 函数名() { ... })不仅把函数名提升,还把整个函数体一起提升。这意味着:即使调用写在声明之前,也能正常执行。
- 引擎在进入执行上下文前,就已将函数名和函数体一同注册进变量对象(VO 或 AO)
- 函数体内容此时已可访问,例如
console.log(func)会输出函数源码,而非undefined - 这种提升是静态的、一次性完成的,不依赖后续代码执行顺序
提升发生在编译阶段,早于任何语句执行
JS 引擎处理一段代码时,先进行语法检查,再进入编译阶段——此时只处理声明,跳过赋值、调用等执行语句。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 所有
function声明被扫描并立即注入作用域,函数体被完整保存 - 若同一作用域内多次声明同名函数,后面声明会覆盖前面的,最终保留的是最后一次的函数体
- 该阶段不会执行函数内部任何代码,只是为后续调用准备好定义
函数声明优先级高于变量声明
当函数名与变量名冲突时,函数声明占据主导地位,变量声明会被忽略或退让。
- 例如:
var foo = 1; function foo() {}→ 编译后foo指向函数,不是1或undefined - 但若写成
function foo() {}; var foo = 1;,则执行阶段foo会被重新赋值为1(变量赋值在执行阶段发生) - 这说明:声明阶段函数胜出,执行阶段赋值才可能改写它
与函数表达式的关键区别
函数表达式(如 var fn = function() {})不享受函数体提升,只提升变量名。
-
fn()若出现在声明前,会报TypeError: fn is not a function - 因为编译阶段只做
var fn;,而fn = function(){}是执行阶段才发生的赋值 - 函数体此时尚未绑定到变量,自然无法调用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










