函数声明以function关键字开头且独立成句,会被完整提升;函数表达式将function作为值使用,只提升变量声明或不提升,适用于回调、立即执行等场景。

最直接的区分方式看语法开头:以 function 关键字开头、后面紧跟函数名和括号的,是函数声明;其他所有用 function 创建函数但不满足这个结构的,都属于函数表达式。
语法形态不同
函数声明必须有名字,且独立成句:
- function greet() { console.log('hello'); } —— 合法声明
- function() { } —— 缺少名字,语法错误(不能单独存在)
函数表达式把 function 当作值来用,常出现在赋值、传参、括号包裹等上下文中:
- const fn = function() {}; —— 赋值右侧
- (function() {})(); —— 括号内立即执行
- [1,2,3].map(function(x) { return x * 2 }); —— 作为参数传递
- const obj = { method: function() {} }; —— 对象属性值
提升行为完全不同
函数声明会被完整提升:函数名和函数体一起提前到作用域顶部,可先调用后定义。
- foo(); // ✅ 正常运行
- function foo() { console.log(1); }
函数表达式只提升变量声明(var)或不提升(let/const),函数体仍在原位置:
- bar(); // ❌ TypeError(var)或 ReferenceError(let/const)
- var bar = function() { console.log(2); };
- const baz = () => 3; baz(); // ❌ ReferenceError(let/const 不允许提前访问)
适用场景有明显倾向
函数声明适合定义主逻辑、命名清晰、需多处调用的函数,比如工具函数、页面初始化入口。
函数表达式更常用于:
- 回调函数(setTimeout(() => {}, 100))
- 立即执行((function() {})() 或 (() => {})())
- 模块导出(export const helper = function() {};)
- 条件创建(const fn = flag ? function a() {} : function b() {};)
命名与作用域表现不同
函数声明的名字在当前作用域中是真实绑定的标识符,可递归调用,也可被 typeof 查到。
命名函数表达式的内部名仅在函数体内有效,外部不可见:
- const f = function named() { return named; };
- f(); // ✅ 返回函数自身(named 在内部可用)
- named; // ❌ ReferenceError
- f.name; // 'named'
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











