函数声明和函数表达式最核心区别在于提升行为与语法位置约束:前者全量提升且只能出现在顶层或函数体,后者仅变量名提升、可置于任意表达式位置,并支持命名但名称仅内部有效。

函数声明和函数表达式在 JavaScript 中最核心的区别在于提升(hoisting)行为和语法位置约束,这直接影响它们的可调用时机和作用域使用方式。
提升机制不同:函数声明会被完全提升,函数表达式只提升变量名
JavaScript 引擎在执行前会进行“提升”处理。对于函数声明,整个函数定义会被提升到当前作用域顶部;而函数表达式只是将 var 声明的变量名 提升,赋值(即函数体)仍保留在原位置。
例如:
foo(); // ✅ 正常运行,输出 "hello"
function foo() { console.log("hello"); }
<p>bar(); // ❌ 报错:TypeError: bar is not a function
var bar = function() { console.log("world"); };</p>这是因为第二段代码实际等价于:
立即学习“Java免费学习笔记(深入)”;
var bar; // 变量声明被提升
bar(); // 此时 bar 是 undefined,调用失败
bar = function() { console.log("world"); }; // 赋值发生在后面
语法位置限制不同:函数声明只能出现在程序顶层或函数体内,不能在条件语句中
函数声明是一种独立的语句,不允许直接写在 if、for、try 等块级结构内部(尽管某些引擎允许,但属于非标准行为,且各浏览器表现不一致)。
函数表达式则没有此限制,它可以作为值出现在任何允许表达式的地方:
- 赋值给变量或对象属性
- 作为参数传入另一个函数
- 立即执行(IIFE)
- 放在 if 分支里动态创建
例如合法的函数表达式用法:
if (condition) {
var fn = function() { return "yes"; };
} else {
var fn = function() { return "no"; };
}
<p>[1, 2, 3].map(function(x) { return x * 2; });</p><p>(function() { console.log("IIFE"); })();</p>名称行为差异:函数表达式可选命名,但名字仅在内部可用
函数声明必须有名字,且该名字在所在作用域中绑定为函数引用。
函数表达式可以是匿名的(如 var f = function() {}),也可以带名字(如 var f = function named() {})。这个“named”只在函数内部用于递归或调试,在外部不可访问:
var f = function named() {
console.log(named); // ✅ 可以访问自身名字
};
console.log(named); // ❌ ReferenceError: named is not defined
console.log(f.name); // ✅ 输出 "named"(现代环境)
严格模式下的额外注意点
在严格模式中,函数声明在块内(如 if 中)会产生语法错误,进一步强调应避免依赖非标准的块级函数声明。而函数表达式天然兼容严格模式,是更安全、更可预测的选择。
现代开发中,推荐优先使用函数表达式(尤其是箭头函数和 const 声明),或使用 ES6 的 const myFn = () => {} 形式,逻辑清晰、无提升陷阱、便于静态分析。










