redux原始碼分析之四:compose函式

Happi發表於2018-09-06

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

相關文章