函数式编程的思想
函数式编程是一种编程范式,它更关注从输入到输出的映射结果的编程思想,他有以下一些思想
函数是一等公民
我的理解就是能用函数就用函数,函数可以做参数、变量、返回值.
举个栗子,比如我们要对数组进行排序
1 | const arr = [1,3,4,2,1] |
为什么方法2比较好?
从复用性的角度来说,当我们很多地方需要使用同样的方法进行排序,那么我们直接引入compare方法即可。
1 | import {compare} from '@/utils' |
从维护性的角度来说,当我们的需求变动,我们只需要修改compare里面即可,或者使用别的compare方法。
比如换个需求变动,更换排序方式为倒置,我们只要很方便的修改sort的入参即可
1 | // 倒置数组 |
在举个参数变化的例子:
1 | // bad |
为什么呢,比如这个时候,我们需要renderPost里面对错误进行处理,
1 | // 胶水函数都需要改 |
可以看到我们少改动了一些代码
纯函数
这是一个数学概念,f(x) = y,纯函数指 x 输入一致,那么 y 也一致。
举个例子:
1 | // 纯函数 |
例子 1 是纯函数,因为当 x 一致,返回永远;
例子 2 不是纯函数,notPureFn依赖了外部变量i,如果这个时候程序外部改变了 i 那么返回的结果就不一致;
纯函数的优点
我们从函数的定义可以不难得出纯函数的几个优点
- 易于单元测试
1 | function sum(a, b) { |
因为纯函数不依赖外部环境,我们可以方便的写出单元测试,不需要为单元测试增加外部环境。
易于重构
因为可以很方便的增加单元测试,重构过程中可以减少很多理解成本bug 可控
因为纯函数不影响外部环境,产生 bug 影响面小。可缓存
因为输入一致,输出也是一致,所以我们可以对此进行缓存。
如何写代码
我们应该要多写纯函数,少写非纯函数。
副作用
副作用指函数内部和外部的交互,比如:
- 发起 http 请求
- 使用外部变量
- 数据库读写
等等
函数式编程要求我们通过拆分,减少副作用函数
组合(compose)
我们可以把函数组合起来,生成一个新的函数,比如g(f(x))或者g.a().b(),但g.a().b()需要放在原型链上,更多的时候我们采用的式g(f(x))这种方式
1 | const data = [1, 2, 3, 4] |
值得注意的是,在这个例子中,sum和square的顺序是不能交换的, 但是有些时候, 组合是可以交换位置的。
最后再写一个通用的compose函数
1 | function compose(...fns) { |
科里化(curry)
通用科里化函数
1 | function curry(fn,...argsOut) { |