3

函数组合是函数式编程中非常重要的思想,它的实现的思路也没有特别复杂。有两种函数组合的方式,一种是pipe,另一种是compose。前者从左向右组合函数,后者方向相反。
下面就是一个最简单的可以组合两个函数的compose

let compose = (f, g) => (...args) => f(g(...args));

在实际应用中,只能组合两个函数的组合函数显然不能满足要求,我们需要可以组合任意个函数的组合函数。下面提供两种思路。

一种思路

两种方法一种是递归,一种是循环,其实都是一样的。具体的思路就是,先写一个组合可以两个函数的compose2,用compose2先把传进来的末尾的两个函数组合了,返回一个函数func,然后再compose2把func和传进来的下一个函数组合起来,以此类推。

循环的方法

let compose2 = (f, g) => (...args) => f(g(...args));
let compose = (...funcArgs) => (...args) => {
  let funced = funcArgs[funcArgs.length - 1];
  for (let i = funcArgs.length - 2; i >= 0; i--) {
    if (i === 0) {
      return compose2(funcArgs[i], funced)(...args);
    }
    funced = compose2(funcArgs[i], funced);
  }
}

// 与compose组合方向相反的函数组合函数
let pipe = (...funcArgs) => compose(...funcArgs.reverse());

递归的方法

let compose2 = (f, g) => (...args) => f(g(...args));
let compose = (...funcArgs) => (...args) => {
  let [...funcArgsCopy] = funcArgs;
  let callSelf = func => {
    if (funcArgsCopy.length === 0) return func;
    let funced = compose2(funcArgsCopy.pop(), func);
    return callSelf(funced);
  }
  return callSelf(funcArgsCopy.pop())(...args);
}

let pipe = (...funcArgs) => compose(...funcArgs.reverse());

更简单的思路

上面的思路还是有点麻烦,其实不用纠结在组合,直接把前一个函数的处理参数之后的返回值传给下一个函数就可以了。
循环的方法

let compose = (...funcArgs) => (...args) => {
  for (let i = funcArgs.length - 1; i >= 0; i--) {
    args = i === funcArgs.length - 1 ? funcArgs[i](...args) : funcArgs[i](args);
  }
  return args;
}

let pipe = (...funcArgs) => compose(...funcArgs.reverse());

递归的方法

let compose = (...funcArgs) => (...args) => {
  let [...funcArgsCopy] = funcArgs;
  let funced = (...func) => {
    if (funcArgsCopy.length === 0) return func[0];
    func = funcArgsCopy.pop()(...func);
    return funced(func);
  }
  return funced(...args);
}

let pipe = (...funcArgs) => compose(...funcArgs.reverse());

我在github https://github.com/zhuanyongx...


砖用西瓜
206 声望13 粉丝