函数组合(compose)从右向左执行,等价于f(g(h(x)));管道(pipe)从左向右执行,等价于h(g(f(x)));二者可互转,pipe(f,g,h)≡compose(h,g,f);推荐优先使用语义更清晰的pipe。

函数组合(Compose)和管道(Pipe)本质都是将多个单参数纯函数串联执行,区别只在于调用顺序:Compose 从右向左执行,Pipe 从左向右执行。两者可互相转换,核心在于理解“数据流方向”与“函数嵌套顺序”的关系。
Compose 是右到左的数据流
Compose 把函数 f、g、h 组合成一个新函数,等价于 f(g(h(x)))。也就是说,输入 x 先被最右边的函数 h 处理,结果传给 g,再传给 f。
典型实现:
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);例如:
const add1 = x => x + 1;const double = x => x * 2;
const toString = x => String(x);
const f = compose(toString, double, add1);
f(3); // "8" → 3 → add1(3)=4 → double(4)=8 → toString(8)="8"
Pipe 是左到右的直观写法
Pipe 更符合阅读习惯:x 先进 add1,再进 double,最后进 toString,即 toString(double(add1(x)))。
实现只需把 reduceRight 换成 reduce:
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);上面例子改用 pipe:
const f = pipe(add1, double, toString);f(3); // "8"
语义更清晰,尤其在处理长链逻辑时(如数据清洗、格式转换)不易出错。
如何用 Compose 实现 Pipe 的效果
不需要重写逻辑,只需反转函数数组顺序:
- pipe(f, g, h) 等价于 compose(h, g, f)
- 所以可直接定义 pipe 基于 compose:const pipe = (...fns) => compose(...fns.reverse());
- 或者更高效地:用 reduce 而非 reverse + compose,避免额外数组拷贝
实际使用建议
- 优先用 pipe:语义明确,调试时从左到右追踪更自然
- compose 适合数学或函数式场景(如范畴论风格代码),或需复用已有右结合习惯的库(如 Ramda 的 R.compose)
- 所有函数必须是单参数纯函数;若遇多参函数,先用柯里化(curry)固定前几个参数
- 可配合工具函数增强可读性,比如命名中间步骤:pipe(add1, double, log("after double"), toString)










