// ① 函数声明:有名字,会「提升」,声明前也能调用
function double(n) { return n * 2 }
// ② 函数表达式:把一个函数存进变量,不提升
const double = function (n) { return n * 2 }
// ③ 箭头函数:回调场景的简写,没有自己的 this(第七章细讲)
const double = (n) => { return n * 2 }
const double = n => n * 2 // 单参数可省括号、单表达式可省 return
函数声明的提升(hoisting)是「整体搬到作用域顶部」,所以先调用后定义没问题;const 箭头函数只有变量提升、且处于 TDZ,先调用直接 ReferenceError。日常建议:用到的函数先定义再调用,别依赖提升。
function greet(name = '游客') { return '你好,' + name }
greet() // '你好,游客' —— 没传参,用默认值
greet(undefined) // '你好,游客' —— undefined 触发默认值
greet('') // '你好,' —— 空串是「传了」的值,不触发默认
greet(null) // '你好,null' —— null 也不触发默认(只有 undefined 会)
function sum(...nums) { // 剩余参数:把所有实参收成一个真数组
return nums.reduce((acc, n) => acc + n, 0)
}
sum(1, 2, 3) // 6
sum(...[1, 2, 3]) // 6 —— 展开运算符反向操作,把数组摊成实参
参数传递规则:**少传的自动为 undefined(再由默认值接手),多传的不会报错**,被 ...剩余参数 收走或直接忽略。旧代码里的 arguments 对象是「类数组」,没有数组方法,新代码统一用剩余参数代替。
function divide(a, b) {
if (b === 0) return '除数不能为 0' // 守卫子句:提前 return,后续代码不再执行
if (typeof a !== 'number' || typeof b !== 'number') return '参数必须是数字'
return a / b // 正常路径放在最后
}
function noReturn() { const x = 1 } // 没有 return → 返回 undefined
function multi() { return { total, count } } // 想返回多个值 → 包成对象
两个小心处:忘记 return 的函数返回 undefined,链式调用时会得到 undefined.xxx 报错;return 后面不要换行,ASI 会自动补分号,把它变成「return 了 undefined」。
| 完整写法 | 简写 | 能省掉什么 |
|---|---|---|
| (a, b) => { return a + b } | (a, b) => a + b | 函数体只有单表达式时,{} 和 return 都能省 |
| (n) => { return n * 2 } | n => n * 2 | 单个参数可省括号 |
| () => { return 42 } | () => 42 | 没有参数时括号不能省 |
| (n) => { return { id: n } } | n => ({ id: n }) | 直接以 {"{"} 开头会被当成函数体,要包一层括号 |
箭头函数适合「一行就说完」的回调(数组方法、事件处理),逻辑一多就换回函数声明或表达式——有名字、有函数体括号、还能用 debugger 断点看到清晰的调用栈。