compose从右向左执行,pipe从左向右执行;用compose实现pipe只需将函数数组逆序传入,如pipe(f,g,h)等价于compose(h,g,f);可封装pipe=...fns=>compose(...fns.reverse())复用compose逻辑。
组合函数(compose)本身默认从右向左执行,比如 compose(f, g, h)(x) 等价于 f(g(h(x)))。而管道(pipe)是直观的从左到右: pipe(f, g, h)(x) 相当于 h(g(f(x)))。所以“用 compose 实现 pipe 的逻辑分层”,关键不是强行改执行方向,而是把处理步骤的顺序倒过来传给 compose——这样数据流依然线性清晰,只是函数定义顺序需调整。
假设你有一组按业务自然顺序排列的处理函数:
trim:去除首尾空格toLowerCase:转小写capitalize:首字母大写用 pipe 表达就是:pipe(trim, toLowerCase, capitalize),语义清晰。 要等效地用 compose 实现相同效果,只需将函数数组逆序传入:compose(capitalize, toLowerCase, trim)。 两者调用结果一致,但 compose 的参数顺序是“最终操作在前,初始处理在后”。
你可以基于 compose 快速导出 pipe,无需重写执行逻辑:
const pipe = (...fns) => compose(...fns.reverse());
这样 pipe(a, b, c) 内部自动转为 compose(c, b, a),既复用了 compose 的实现,又保留了 pipe 的阅读习惯。实际项目中,很多工具库(如 Lodash 的 flow)正是这样做的。
无论用 compose 还是 pipe,真正支撑“逻辑分层”的是函数本身的职责单一和命名明确:
validateEmail、formatPhone、maskSSN
sanitizeUserInput = pipe(trim, toLowerCase, validateEmail)
对于返回 Promise 的函数,如 fetchUser → enrichProfile → cacheLocally:
asyncPipe(fetchUser, enrichProfile, cacheLocally)
compose(cacheLocally, enrichProfile, fetchUser),并确保每个函数能处理 Promise 输入本质没变:数据流向仍是单向穿透,只是函数声明顺序与执行顺序是否一致的问题。