歡迎關注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函式執行後,返回值是另外一個函式,這個函式,其實只是做了一件事情:把一個函式陣列,按照順序,從陣列最後向前按照順序執行,並且,把前一個執行的函式返回值,作為下一個執行函式的入參。對,你沒看錯,就是這麼簡單!