选函数声明还是函数表达式,关键看三点:能否提前调用、是否需要命名、使用位置。函数声明可提升,支持前置调用;函数表达式受作用域约束,适合闭包、高阶函数、iife;具名函数表达式利于调试和递归。

选函数声明还是函数表达式,关键看三点:能不能提前调用、需不需要命名、用在什么位置。
需要在定义前调用,就用函数声明
函数声明会被提升(hoisting),整个函数体在代码执行前就已就位,所以可以写在文件末尾,却在开头就调用:
-
能这样写且不报错:
sayHello(); function sayHello() { console.log('Hi'); } -
函数表达式做不到:
sayHello(); const sayHello = function() {}会报TypeError: sayHello is not a function - 适合工具函数、初始化逻辑、模块顶层的通用方法
要控制作用域或作为值传递,就用函数表达式
函数表达式本质是“把函数当数据”,赋值给变量后受 let/const 规则约束,不会意外暴露到外层作用域:
- 适合闭包内部私有函数:
function createCounter() { const inc = function() { return ++count; }; return { inc }; } - 作为参数传入高阶函数更自然:
[1,2,3].map(function(x) { return x * 2; })或setTimeout(() => {}, 100) - 支持立即执行(IIFE):
(function() { console.log('run once'); })();—— 函数声明不能直接这么用
调试和递归需求强,优先用具名函数表达式
匿名函数表达式(const fn = function() {})在堆栈里显示为 anonymous,难定位;而具名写法(const fn = function handler() {})能让 DevTools 显示 handler:
- 错误堆栈更清晰,断点也更容易停在正确位置
- 若需在函数内递归调用自身,必须具名:
const factorial = function fact(n) { return n - 注意:名字
fact只在函数体内有效,外部仍通过factorial调用
箭头函数不是第三种选择,而是函数表达式的简化写法
它没有自己的 this、arguments,也不能用 new,本质上属于表达式范畴:
- 适合简短回调:
arr.map(x => x * 2)、btn.addEventListener('click', () => doSomething()) - 不适用于需要动态
this的场景(如对象方法)、构造函数、需要arguments的老式参数处理 - 不能递归(无
name属性,也无法在内部引用自己)











