redux源碼分析之四:compose函數

歡迎關注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

相關文章
相關標籤/搜索