概念

compose函数: 将需要嵌套执行的函数平铺。
嵌套执行指的是:一个函数的返回值将作为另一个函数的参数。

其实compose在函数式编程中,就是将几个有特点的函数拼凑在一起,让他们结合产生一个崭新的函数

compose函数作用:实现函数式编程中的Pointfree,使我们专注于转换而不是数据。

也就是说,我们可以把数据处理的过程定义成一种与参数无关的合成运算,不需要用到代表数据的那个参数,只要把一些简单的运算步骤合成在一起即可。

Pointfree指的是:不使用所要处理的值,只合成运算过程,即所谓的无参数分割

compose参数函数的调用是从右往左,webpack的loader也是从右往左,因为它使用了compose函数。

示例

我们现在有这么一个需求:求一个数值先加10再乘10 的结果。

命令式方式

  1. let fn = x => (x + 10) * 10
  2. console.log(fn(10)); // 200

初级FP

将所要执行的动作进行分解,动作1(add):+10,动作2(multi):*10

  1. const add = x => x + 10
  2. const multi = x => x * 10;
  3. console.log(multi(add(10))) // 200

初级compose

使用compose函数将add与multi整合,并确保其从右往左执行

  1. const add = x => x + 10
  2. const multi = x => x * 10;
  3. const compose = (f, g) => {
  4. return x => {
  5. return f(g(x))
  6. }
  7. }
  8. console.log(compose(multi, add)(10)) // 200

当然这个compose函数没有通用性,只能接受两个参数,下面我们进行改造

通用compose

使用reduce函数对参数函数进行累计执行,因为是从右向左执行,所以使用reduceRight

  1. const add = x => x + 10
  2. const multi = x => x * 10;
  3. const compose = function() {
  4. const args = [].slice.call(arguments);
  5. return function(x) {
  6. return args.reduceRight(function(res, cb) {
  7. return cb(res)
  8. }, x)
  9. }
  10. }
  11. console.log(compose(multi, add)(10)) // 200

终极compose

使用箭头函数对compose函数再次进行简化

  1. const compose = function() {
  2. const args = [ ...arguments ];
  3. return x => args.reduceRight((res, cb) => cb(res), x)
  4. }

注意:箭头函数与arguments

如果上边的代码写成这样,是会报错的:

  1. const compose = () => {
  2. const args = [ ...arguments ];
  3. return x => args.reduceRight((res, cb) => cb(res), x)
  4. }

因为箭头函数是没有绑定Arguments对象的,所以这里的arguments是拿不到正确的值的。

我们可以使用…剩余运算符解决这个问题:

  1. const compose = (...args) => x => args.reduceRight((res, cb) => cb(res), x)

这就是终极compose函数。