函数组合(compose)从右往左执行,如f(g(h(x))),适合数学风格的底层先行逻辑;管道(pipe)从左往右执行,如清洗→转换→过滤,更符合自然语言顺序,便于调试与异步链式处理。

函数组合(Compose)和管道(Pipe)是函数式编程中组织逻辑的核心手段,本质都是把多个纯函数串成一条数据流水线:前一个的输出自动成为后一个的输入。它们不改变原始数据,也不依赖外部状态,只专注“转换”。关键区别在于执行顺序——compose 从右往左,pipe 从左往右,选哪个取决于你读代码时更习惯“先做什么、再做什么”。
compose:数学风格的右向结合
compose 模拟数学中的复合函数记号 f ∘ g,即 f(g(x))。它适合表达“先处理底层、再做包装”的逻辑,比如解析 → 格式化 → 渲染。
- 实现简洁:
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x); - 调用示例:
const shout = compose(exclaim, toUpperCase); shout('hello');等价于exclaim(toUpperCase('hello')),结果是'HELLO!' - 注意顺序:写
compose(f, g, h)表示f(g(h(x))),最右边的h最先执行
pipe:线性可读的数据流
pipe 更贴近自然语言描述,像“清洗 → 转换 → 过滤 → 输出”,每一步都清晰可见,特别适合数据处理链。
- 实现方式:
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x); - 实际用例:
const processEmail = pipe(trim, toLowerCase, validateEmail);输入字符串,依次去空格、转小写、校验格式 - 便于调试:可在任意环节插入
tap(console.log)查看中间值,不影响主流程
与柯里化配合提升复用性
单独的组合函数只是“连接器”,真正发挥威力需要搭配柯里化(Currying)。例如:
- 定义一个可配置的验证器:
const hasMinLength = min => str => str.length >= min; - 组合进管道:
pipe(trim, hasMinLength(3), isValidDomain) - 这样同一套处理链,只需改参数就能适配不同业务场景,无需重写整条流水线
异步操作也能走管道
Promise 链天然符合管道思想。只需让 reduce 异步等待即可:
const asyncPipe = (...fns) => value => fns.reduce((acc, fn) => acc.then(fn), Promise.resolve(value));- 使用:
asyncPipe(fetchUser, enrichProfile, saveCache)(123),每个函数返回 Promise,自动串行执行 - 错误统一在最后用
.catch()处理,避免分散的 try/catch
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











