歡迎關注redux源碼分析系列文章:
redux源碼分析之一:createStore.js
redux源碼分析之二:combineReducers.js
redux源碼分析之三:bindActionCreators.js
redux源碼分析之四:compose.js
redux源碼分析之五:applyMiddlewareredux
redux的compose函數實在太精妙,總共才9行,真正的代碼其實才1行,看下源文件代碼以下:segmentfault
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函數執行後,返回值是另一個函數,這個函數,其實只是作了一件事情:把一個函數數組,按照順序,從數組最後向前按照順序執行,而且,把前一個執行的函數返回值,做爲下一個執行函數的入參。對,你沒看錯,就是這麼簡單!app