Logo
Section 1 / 3

管道(Pipe)

你已经会组合函数了。Pipe 让你以从左到右的方式进行组合,提升代码的可读性。(4分钟阅读)

导入

管道(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 让你可以从 左到右 组合函数,将它们组织成一系列事件的顺序。最左边的函数先执行,然后将其结果传给下一个函数,依此类推。

最终得到的结果,非常接近你在构思解决方案时所写的说明:

  1. 获取名字
  2. 转为大写
  3. 反转
1pipe( 2 getFirstName, 3 uppercaseString, 4 reverseString 5)

看到了相似之处吗?下面是一个动画演示,展示 Bobo 如何穿过这个函数管道。

Bobo running through the pipe
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 });

柯里化

组合(Compose)