复合函数的定义
复合函数是指把两个函数链接在一起,内函数的输出即为外函数的输入。
例如,定义一个复合函数compose,简单来讲,它应该实现如下效果:
compose(f, g)(args) = f(g(args))
Redux 源码中的复合函数
export default function compose(...funcs: Function[]) {
if (funcs.length === 0) {
// infer the argument type so it is usable in inference down the line
return <T>(arg: T) => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args: any) => a(b(...args)))
}
这个方法接收一个函数数组 Function[],处理后返回一个函数。
首先,当输入的参数长度为零时,简单地返回一个仅返回所有参数本身的函数。当输入的参数长度为一时,仅仅输入了一个函数,也遑论「组合」,直接返回即可。
剩下的便是输入的参数大于一的情况,亦即有多个函数需要被组合。
这里使用了 Array.prototype.reduce() 方法。这个方法接收一个回调函数和一个初始值,从前往后对数组进行处理。当没有提供初始值时,这个方法会将数组中的第一个元素作为初始值,从第二个元素开始进行处理。此处便是没有传入初始值的情况。
为了便于理解,可以假设传入的参数为 compose(func1, func2, func3),一步一步来看:
funcs 为 [func1, func2, func3],未提供初始值,以 func1 为初始值,从 func2 开始迭代。
- 第一次迭代
a = func1 // 初始值
b = func2 // 当前元素
// a, b 分别代入 (...args: any) => a(b(...args))
return (...args: any) => func1(func2(...args)) // 返回的下一次迭代的初始值
- 第二次迭代
a = (...args: any) => func1(func2(...args)) // 初始值
b = func3 // 当前元素
return (...args: any) => a(b(...args))
将新的初始值 a((...args: any) => func1(func2(...args))) 和当前元素 b(func3) 分别代入返回的结果 (...args: any) => a(b(...args)) 可得,此次迭代的返回为:
return (...args: any) => (
(...args: any) => func1(func2(...args))
)(func3(...args))
将 func3(...args) 代入 (...args: any) => func1(func2(...args)) 可得:
return (...args: any) => func1(func2(func3(...args)))
可见,最终返回的即为复合后的结果 func1(func2(func3(...args)))。