1. 概念

柯里化函数编程思想:Currying(柯里化)是将一个带有多个参数的函数转换为函数序列的过程,每个函数只有一个参数。

一个有n个参数的函数,可以使用柯里化将它变成一个一元函数。

  1. const binaryFunction = (a, b) => a + b;
  2. const curryUnaryFunction = a => b => a + b;
  3. curryUnaryFunction(1); // returns a function: b => 1 + b
  4. curryUnaryFunction(1)(2); // returns the number 3

柯里化函数非常适合提高代码的可重用性和函数式结构。

  1. 执行一个方法,传递一些参数进去,首先形成一个不销毁的私有作用域,把传递的这些值存储起来(没有立即使用,属于预先存储起来)

  2. 返回一个小函数给私有作用域外面的

  3. 当执行返回的小函数的时候,把之前第一步预先存储的信息拿过来使用(作用域链、闭包等机制完成的)

我们利用 JS 中基于闭包实现的预先存储的思想完成函数的柯里化。

2. 管道机制

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

  1. const add1 = (x) => x + 1;
  2. const mul3 = (x) => x * 3;
  3. const div2 = (x) => x / 2;
  4. div2(mul3(add1(add1(0)))) //=> 3

上面的写法可读性明显太差,我们可以构建一个 compose 函数,它接受任意多个函数作为参数(这些函数都只接受一个参数),然后 compose 返回的也是一个函数,达到管道的效果。

  1. const operate = compose(add1, add1, mul3, div2);
  2. operate(0) //=> 3

compose 函数编写

  1. //=> 字符串拼接成:div2(mul3(add1(add1(0)))) 这种形式,然后再使用 eval 执行它
  2. const compose = (...funcs) => {
  3. funcs = funcs.reverse();
  4. return val => {
  5. let str = '';
  6. funcs.forEach((func) => {
  7. str = str + func.name + ',';
  8. });
  9. str.replace(/,/g, '(');
  10. str += val;
  11. funcs.forEach(item => (str +=')'));
  12. return eval(str);
  13. }
  14. }
  15. //=> 利用数组的 forEach 方法,每次遍历之后让 val 赋值为上一次的执行结果
  16. const compose = (...funcs) => {
  17. return val => {
  18. funcs.forEach(func=> {
  19. val = func(val);
  20. })
  21. }
  22. }
  23. //=> 利用数组的 reduce 方法
  24. const compose = (...arg) => {
  25. return val => {
  26. //=> 将 val 作为归并的初始值,a 为上一次函数执行的返回值,b 为当前项的值
  27. arg.reduce((a, b) => {
  28. return b(a);
  29. }, val);
  30. }
  31. }
  32. //=> 简化
  33. const compose= (...funcs) =>
  34. val => funcs.reduce((a, b) => b(a), val);