写一个compose函数

# 写一个compose函数

组合多个函数,从右到左,比如:compose(f, g, h) 最终得到这个结果 (...args) => f(g(h(...args))).

实现

function compose(...funcs) {

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
1
2
3
4
5
6
7
8

compose创建了一个从右向左执行的数据流。如果要实现从左到右的数据流,可以直接更改compose的部分代码即可实现

  • 更换Api接口:把reduce改为reduceRight
  • 交互包裹位置:把a(b(...args))改为b(a(...args))

compose 函数演化

传入一个数值,计算数值乘以10再加上10,再减去2

实现起来很简单。

const calc = (num) => num * 10 + 10 - 2;
calc(10); // 108
1
2

但这样写有个问题,不好扩展,比如我想乘以10时就打印出结果。 为了便于扩展,我们分开写成三个函数。

const multiply = (x) => {
   const result = x * 10;
   console.log(result);
   return result;
};
const add = (y) => y + 10;
const minus = (z) => z - 2;

// 计算结果
console.log(minus(add(multiply(10))));
// 100
// 108
// 这样我们就把三个函数计算结果出来了。
1
2
3
4
5
6
7
8
9
10
11
12
13

再来实现一个相对通用的函数,计算这三个函数的结果

const compose = (f, g, h) => {
  return function(x){
    return f(g(h(x)));
  }
}
const calc = compose(minus, add, multiply);
console.log(calc(10));
// 100
// 108
1
2
3
4
5
6
7
8
9

这样还是有问题,只支持三个函数。我想支持多个函数。 我们了解到数组的reduce方法就能实现这样的功能。 前一个函数

const compose = (...funcs) => {
  return funcs.reduce((a, b) => {
    return function(x){
      return a(b(x));
    }
  })
}
const calc = compose(minus, add, multiply);
console.log(calc(10));
// 100
// 108
1
2
3
4
5
6
7
8
9
10
11
上次更新: 2022/7/2 下午3:22:19