高级函数技巧-compose

普通函数

1
2
3
4
5
const add10 = (x) => x + 10;
const mul10 = (x) => x * 10;
const add100 = (x) => x + 100;

console.log(add10(mul10(add100(10)))); // (10 + 100) * 10 + 10 = 1110

我们想输出的是一个多层函数嵌套的运行结果,即把前一个函数的运行结果赋值给后一个函数。但是如果需要嵌套多层函数,那这种类似于 f(g(h(x)))的写法可读性太差,我们考虑能不能写成(f, g, h)(x)这种简单直观的形式,于是 compose()函数就正好帮助我们实现。

compose

compose 函数是一种函数式编程的概念,它可以将多个函数组合成一个新的函数。在 JavaScript 中,compose 函数的实现通常是使用 reduceRight 方法,从右到左依次执行每个函数。

在函数式编程当中有一个很重要的概念就是函数组合, 实际上就是把处理数据的函数像管道一样连接起来, 然后让数据穿过管道得到最终的结果。

1
compose(add10, mul10, add100)(10);

概念

  • 将需要嵌套执行的函数扁平化处理(平铺)
  • 嵌套执行指的是,一个函数的返回值将作为另一函数的参数
  • 实质是在函数式编程中,将几个具有特点的函数拼凑在一起,让他们结合,形成一个崭新的函数

作用

  • 实现函数式编程中的 Pointfree(无参数), 使我们专注于转换而不是数据

  • 编程更精练、算法更清晰、无参数干扰

  • 任意组合

缺点

不能直观的看到参数

实现

接收多个函数作为参数,从右到左,一个函数的输入为另一个函数的输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function compose(...funcs) {
//=>funcs:传递的函数集合
console.log("---funcs---", funcs);
return function proxy(...args) {
//=>args:第一次调用函数传递的参数集合
let len = funcs.length;
if (len === 0) {
//=>一个函数都不需要执行,直接返回args
return args;
}
if (len === 1) {
//=>只需要执行一个函数,把函数执行,把其结果返回即可
return funcs[0](...args);
}
//方式一
return funcs.reduceRight((x, y) => {
console.log("--x--", x);
console.log("--y--", y);
return typeof x === "function" ? y(x(...args)) : y(x);
});
//方式二
return funcs.reverse().reduce((x, y) => {
console.log("--x--", x);
console.log("--y--", y);
return typeof x === "function" ? y(x(...args)) : y(x);
});
};
}

在这个实现中,compose 函数接受一系列的函数作为参数,然后返回一个新的函数。这个新的函数接受一个初始值,然后使用 reduceRight 方法从右到左依次调用每个函数,每次调用的结果作为下一次调用的输入。

所以,compose(add10, mul10, add100)(10) 的执行过程是:

  1. 首先调用 add100(10),得到结果 110。
  2. 然后调用 mul10(110),得到结果 1100。
  3. 最后调用 add10(1100),得到结果 1110。

这就是 compose 函数的工作原理。