导入
管道(Pipe)
你已经会组合函数了。Pipe 让你以从左到右的方式进行组合,提升代码的可读性。(4分钟阅读)
到目前为止,我们已经学习了高阶函数(HOFs)、数据置后(data-last)的函数、柯里化和无点式风格。它们都与什么有关?
函数组合。
它们存在的全部意义就是为了让我们更容易地进行函数组合。当函数需要处理多个涉及数据的步骤时,这一点尤为明显。
回到 Bobo
让我们重新回顾一下“函数组合”章节中的第一个练习:将 Bobo 的名字转为大写并反转。一个拆分后的解决方案可能如下所示:
1const getFirstName = (user) => {...} 2const uppercaseString = (string) => {...} 3const reverseString = (string) => {...} 4 5const upperAndReverseFirstName = (user) => { 6 const name = getFirstName(user); 7 const uppercasedName = uppercaseString(name); 8 9 return reverseString(uppercasedName); 10};
你是否注意到,我们需要中间变量来跟踪数据在各个函数之间传递的过程?
1越复杂 === 越多变量
函数步骤越多,就需要越多的中间变量。这会让代码变得杂乱,并限制代码的声明式表达能力。
你可能会尝试嵌套调用,但我觉得那样看起来更糟糕:
1const upperAndReverseFirstName = (user) => ( 2 reverseString(uppercaseString(getFirstName(user))); 3);
那试试这个呢?
1import { pipe } from 'ramda'; 2 3const upperAndReverseFirstName = pipe( 4 getFirstName, 5 uppercaseString, 6 reverseString 7); 8 9const result = upperAndReverseFirstName({ 10 firstName: 'Bobo' 11}); 12 13console.log({ result });
pipe 让你可以从 左到右 组合函数,将它们组织成一系列事件的顺序。最左边的函数先执行,然后将其结果传给下一个函数,依此类推。
最终得到的结果,非常接近你在构思解决方案时所写的说明:
- 获取名字
- 转为大写
- 反转
1pipe( 2 getFirstName, 3 uppercaseString, 4 reverseString 5)
看到了相似之处吗?下面是一个动画演示,展示 Bobo 如何穿过这个函数管道。

Bobo running through the pipe
这里还有一个交互示例。我们正在对一个数字进行变换:
1import { pipe } from 'ramda'; 2 3const doMath = pipe( 4 // 乘以2 5 (x) => x * 2, 6 7 // 乘以3 8 (x) => x * 3, 9 10 // 平方 11 (x) => x * x, 12 13 // 加1 14 (x) => x + 1 15); 16 17const result = doMath(2); 18 19console.log({ result });