组合的核心概念
组合模式的核心理念是让每个函数专注于一个小任务,然后通过组合这些函数创建更复杂的功能。这种方法有几个关键优势:
- 关注点分离 - 每个函数只负责一个明确的任务
- 易于测试 - 小型纯函数更容易进行单元测试
- 代码复用 - 可以在不同场景中重复使用这些基础函数 4.可维护性 - 更容易理解和修改
🌰 基础方法与组合方法对比
看一个生成随机整数的例子:
🍐 正常使用
1 | /* 产生随机数,带小数 */ |
使用组合模式,我们可以更优雅地完成相同的任务:
1 | /** 简单的 compose 方法,接受两个方法从右至左执行 */ |
这种写法不仅更简洁,还能提高函数的可复用性。
tips: 观察
compose
可知,组成出来的新函数是一元函数
, 如果需要组合多元函数
. 可使用柯里化
|偏函数
🎵 结合律:组合的强大特性
函数组合的一个重要特性是满足结合律,即:
1 | // 伪代码 二者执行后的结果是完全等价的 |
这意味着组合的顺序是灵活的,只要保持函数执行的顺序不变。例如:
1 | /* 按空格切割单词 */ |
基于以上的特性,开发者可以放心大胆的组合函数。如果需要添加新的功能属性,仅需要再 compose
组合一遍,例如想在函数执行时添加一个打印调试
1 | // 添加打印 |
以上就是 compose
的运行机制,数据流是从右往左(顺序不可变)。还有另外一种数据流的方式从左往右,即管道 pipeline
或称序列 sequence
🦌 管道:另一种数据流方向
pipe
单纯是 compose
的复制品,仅仅是改变了数据流的方向
🍐 定义pipe
1 | const pipe = (fnLeft, fnRight) => { |
tips:
pipe
具有compose
一样的功能和特性, 二者是等价的。但在程序开发中最好指定其中一种方式,避免数据混乱
💡 |
管道符
在 unix
系统中,可以使用管道符 |
将结果输入到下一个指令中
1 | # cat 01.txt 输入文本 => grep 从结果中查询 world 字符 |
🍐 Point Free
将一些对象自带的方法转化为纯函数,不要转瞬即逝的中间变量
1 | // 🙅🏻♀️ 转瞬即逝的变量 `toUpperCase()` |
💡 扩展应用
函数组合和管道不仅可用于简单的数据转换,还可应用于:
- 异步操作链 - 结合Promise处理异步数据流
- 数据验证链 - 创建一系列验证函数并组合使用
- 事件处理 - 构建事件处理管道
- 中间件系统 - 类似Express的中间件模式
实现多函数组合
我们的简单compose只支持两个函数,更实用的组合函数应该支持多个函数
1 | const compose = |