← 中文资源

简体中文版本

从左到右组合函数的 pipe 与 compose

用 pipe 按从左到右顺序串联函数,并提供反向的 compose,附带参数校验。

阅读英文原文

功能说明

该示例提供两个最小化的函数组合工具。pipe 把多个单参数函数按从左到右的顺序串起来,前一个的输出作为后一个的输入;compose 顺序相反,更贴近数学写法。它们可以把去空格、转小写、替换字符这类小步骤拼成可读的数据清洗管线,而不必嵌套多层调用。

关键代码

pipe 先校验所有参数都是函数,再返回一个接收初始值的函数,内部用 reduce 依次调用。空参数列表返回恒等函数,因此 pipe() 可以安全地作为默认变换。compose 复用 pipe,并在传入前反转参数数组,反转只影响本次调用的局部数组,不会修改调用方传入的数组本身。两个函数都保持同步,不处理 Promise。

使用注意

每个被组合的函数只能接收一个参数,需要多参数时应先用闭包固定其余参数。函数中的 this 不会自动传递,依赖 this 的方法应改为显式参数。组合顺序错误是常见问题,pipe 是从左到右,compose 是从右到左。管道中任何一步抛错都会中断后续步骤,需要容错时应在单个函数内部处理。异步流程请使用 async 版本的组合器。

验证方式

用 trim、toLowerCase、replace 三步 pipe 处理带空格的 Hello World,断言得到 hello-world。用 compose 组合乘二与加一,断言输入 3 输出 8,验证从右到左的顺序。测试空 pipe 返回原值、传入非函数抛 TypeError,并确认原始函数数组未被修改。

代码示例

export function pipe(...functions) {
  assertFunctions(functions);
  return function piped(value) {
    return functions.reduce((current, fn) => fn(current), value);
  };
}

export function compose(...functions) {
  assertFunctions(functions);
  return pipe(...functions.reverse());
}

function assertFunctions(functions) {
  for (const fn of functions) {
    if (typeof fn !== "function") throw new TypeError("all arguments must be functions");
  }
}

const normalize = pipe(
  (value) => value.trim(),
  (value) => value.toLowerCase(),
  (value) => value.replace(/\s+/g, "-"),
);
console.log(normalize("  Hello   World  "));

const calculate = compose(
  (value) => value * 2,
  (value) => value + 1,
);
console.log(calculate(3));