# 实现compose函数

redux源码里有用到 工具函数compose

compose函数 的作用是 把 “接收到的函数” 合成为一个 “最终函数”。

若向这个 “最终函数” 传参,就相当于 “从右到左” 依次执行 “接收到的函数”。

# 特点

  • 参数均为函数,返回值也是函数
  • “最右的函数” 可接收多个参数;“其它函数” 只可接收一个参数(即上一个函数的返回值)

# 例子

let sayHello = (...str) => `Hello , ${str.join(" And ")}`; 
let toUpper = str => str.toUpperCase(); 

let combin = compose(toUpper, sayHello); 
combin("jack", "bob"); // HELLO , JACK AND BOB
1
2
3
4
5

# 实现

  • lodash 的 实现思路: 最后一个函数apply + 其它函数call
  • redux 的 实现思路: reduce
// lodash 中的 compose
function compose (...funcs) {
    // 1. 记录 传入函数的个数
    let length = funcs.length;

    return function(...arg) {
        // 如果没有传入函数,直接返回参数
        if (!length) return arg;

        // 2. 从最右边开始遍历(因为 “最右边的函数” 可接受多个参数)
        let i = length - 1;
        let result = funcs[i].apply(this, arg); //注意 arg 为数组,要用apply

        // 3. 每次执行 i - 1,执行剩下的函数(因为 “其他函数” 只可接受一个参数,即上个函数的返回值)
        while(--i >= 0) {
            result = funcs[i].call(this, result);
        }
        return result;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// redux 中的 compose
// 特点:“从右往左” 执行函数,最右一个函数可传多个参数,其他函数接收上一个函数的返回值
function compose (...funcs) {
    if (funcs.length === 0) {
        return arg => arg;
    }

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

    return funcs.reduce((total, cur) => (...args) => total(cur(...args)));
}

// compose(f1, f2, f3) 执行过程
// => funcs.reduce((total, cur) => (...args) => total(cur(...args)));
// loop1: total = f1, cur = f2, ret1 = (...args) => f1(f2(...args))
// loop2: total = ret1, cur = f3, ret2 = (...args) => ret1(f3(...args))
// 即:ret2 = (...args) => f1(f2(f3(...args)));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 参考

更新时间: 11/21/2021, 2:45:24 AM