函数表达式作参数的核心在于明确意图、控制副作用、简化调用链:聚焦行为语义角色,避免嵌套与临时匿名函数,统一错误处理与空值安全,并借助类型系统约束契约。

把函数表达式当参数传,核心不是“怎么传”,而是“怎么让这个传法真正有用、不绕弯、不埋坑”。关键在三点:明确意图、控制副作用、简化调用链。
聚焦函数表达式的语义角色
函数作为参数,本质是传递“行为”而非“数据”。先问清楚:它负责过滤?转换?校验?还是回调通知?不同角色决定封装粒度和命名方式。
- 过滤逻辑(如
filter(arr, x => x > 0))—— 接口统一用predicate或shouldKeep命名,避免模糊的fn - 转换逻辑(如
map(arr, x => x * 2))—— 明确叫transform,且返回值类型应与输入可预期匹配 - 副作用逻辑(如日志、上报)—— 单独抽成
onSuccess/onError,不混入纯计算流程
避免嵌套过深和临时匿名函数
连续多层函数传参容易变成“括号地狱”,可读性断崖下跌。优先复用已定义的函数,或提前构造闭包。
- ❌ 不推荐:
process(data, x => validate(x) ? transform(x) : fallback(x)) - ✅ 更清晰:
const handler = compose(validate, transform, fallback); process(data, handler) - 需要捕获上下文时,用闭包预置参数:
const checkInGroup = groupId => user => user.groupId === groupId;,调用时只需filter(users, checkInGroup(123))
统一错误处理与空值安全
函数表达式一旦执行出错,往往直接崩掉主流程。应在框架层做兜底,而不是每个调用点都加 try-catch。
- 对传入函数做基础校验:
if (typeof fn !== 'function') throw new TypeError('Expected function') - 提供默认行为:
fn?.(item) ?? defaultValue,尤其在 map/filter 中避免 undefined 泄漏 - 异步函数场景下,统一用 Promise 包装或提供
asyncFn专用签名,不混用同步/异步逻辑
配合类型系统提前约束行为
动态语言里,函数签名靠文档和经验;加类型注解(如 TypeScript)能直接暴露逻辑契约。
- 定义接口:
type FilterFn<t> = (item: T, index: number, array: T[]) => boolean</t> - 让 IDE 和编译器检查参数数量、返回类型、是否可能返回 null
- 泛型化通用函数:
function pipe<t>(...fns: Array T>): (x: T) => T</t>,避免手动推导类型

















