函数组合 compose

179 阅读1分钟

先来看一个列子:
需求: 计算一个数先加上10再乘以10的值。

初始版本:

let calculation = x => (x + 10) * 10;
console.log(calculation(10)); // 200

命令式编程,不具备复用性

优化第一版:

let add = x => x + 10;
let multiply = y => y * 10;
let calculation = x => multiply(add(x));
console.log(calculation(10)); // 200

函数式编程,将程序分解成更可重用、更易于理解的函数,再将函数组合起来形成一个更易于推理的整体

优化第二版:

let add = x => x + 10;
let multiply = y => y * 10;
let compose = (f, g) => {
  return function(x) {
    return f(g(x));
  };
};
let calculation = compose(multiply, add);
console.log(calculation(10)); // 200

根据组合函数的定义,我们需要将两个函数组合为一个函数
特点1: 两个函数都有一个参数;
特点2: 函数的执行顺序是从右到左;
特点3: 前面函数的执行结果是下一函数的参数

优化第三版:

let add = x => x + 10;
let multiply = y => y * 10;

let compose = (...args) => {
  return function(x) {
    return args.reduceRight(function(res, fun) {
      return fun(res);
    }, x);
  };
};

let calculation = compose(multiply, add);
console.log(calculation(10)); // 200

通用compose函数, 符合上面3点特性的同时,不限制组合的函数的个数

优化第四版:

let add = x => x + 10;
let multiply = y => y * 10;

let compose = (...args) => x => args.reduceRight((res, fun) => fun(res), x);

let calculation = compose(multiply, add);
console.log(calculation(10)); // 200

es6写法, 简化代码

总结

compose函数可以将需要嵌套执行的函数平铺,让我们专注于转换而不是数据
嵌套执行指的是 一个函数的返回值将作为另一个函数的参数