欢迎关注redux源码分析系列文章:
redux源码分析之一:createStore.js
redux源码分析之二:combineReducers.js
redux源码分析之三:bindActionCreators.js
redux源码分析之四:compose.js
redux源码分析之五:applyMiddleware
redux的compose函数实在太精妙,总共才9行,真正的代码其实才1行,看下源文件代码如下:
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
但是,就是这最后一行代码,不仔细分析,实在难以理解,我写了注释如下:
export default function compose(...funcs) {
//如果参数长度为0,则返回一个最简单的函数,即传入什么,就返回什么的函数
if (funcs.length === 0) {
return arg => arg
}
//如果参数长度为1,则将参数列表中的第一个函数作为返回值
if (funcs.length === 1) {
return funcs[0]
}
//如果参数长度大于1,则对funcs列表执行reduce函数,
//reduce方法会将(...args) => a(b(...args))整体作为一个返回值,赋值给a变量,b是funcs数组中的下一个函数
//一开始,a,是funcs数组中的第一个函数,b是funcs数组中第二个函数,每执行一次reduce操作,a会被reduce函数中的返回值重新赋值,
// 而reduce函数的返回值刚刚好是一个函数,即a = (...args) => a(b(...args)),
// 由于a就是一个函数,下一轮reduce,新的a函数又会把funcs中下一个函数b作为参数执行,并继续返回下一个a函数
//比如funcs = [f1, f2, f3, f4], 执行流程如下
// a1 = (...args) => f1(f2(...args))
// a2 = (...args) => a1(f3(...args))
// a3 = (...args) => a2(f4(...args))
// 依次代入,则得到
// a2 = (...args) => f1(f2(f3(...args)))
// a3 = (...args) => f1(f2(f3(f4(...args))))
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
所以,这个compose函数执行后,返回值是另外一个函数,这个函数,其实只是做了一件事情:把一个函数数组,按照顺序,从数组最后向前按照顺序执行,并且,把前一个执行的函数返回值,作为下一个执行函数的入参。对,你没看错,就是这么简单!