Compose(…funcs)

/**
 * compose(f,h,g)(...args) => f(g(h(...args)))
 * 使用了 reduceRight, 从右开始执行
 * @param {多个函数, 逗号隔开}
 * @return {函数}
 */

export default function compose(...funcs){
  if(funcs.length === 0){
    return arg => arg
  }

  if(funcs.length === 1){
    return funcs[0]
  }

  const last = funcs[funcs.length - 1]
  const rest = funcs.slice(0,-1)
  return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}
`</pre>

关键在于 reduceRight 可以传入初值

### createStore(reducer, [initialState])

<pre>`import isPlainObject from 'lodash/isPlainObject'
import $$observable from 'symbol-observable'

export var ActionTypes = {
  INIT: '@@redux/INIT'
}

export default function createStore(reducer, preloadState, enhancer){
  var currentReducer = reducer
  var currentState = preloadState
  var currentListeners = []
  var nextListeners = currentListeners
  var isDispatching = false
}

function ensureCanMutateNextListeners(){
  if(nextListeners === currentListeners){
    nextListeners = currentListeners.slice()
  }
}

function getState(){
  return currentState
}

function subscribe(listener){
  if(typeof listener !== 'function'){
    throw new Error('Expected listener to be a function')
  }

  var isSubscribed = true

  ensureCanmutateNextListener()
  nextListeners.push(listener)

  return function ubsubscribe(){
    if(!isSubscribe){
      return
    }
    isSubscribe = false

    ensureCanMutateNextListeners()
    var index = nextListeners.indexOf(listener)
    nextListeners.splice(index,1)
  }
}

function dispatch(action){
  if(isPlainObecjt(action)){
    throw new Error('Action must be plain objects ' + 'Use custom middleware for async action')
  }

  if(typeof action.type === 'undefined'){
    throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?')
  }

  if(isDispatching){
    throw new Error('Reducers may not dispatch actions.')
  }

  try{
    isDispatching = true
    currentState = currentReducer(currentState, action)
  } finally {
    isDispatching = false
  }

  var listeners = currentListeners = nextListeners

  for(var i = 0; i&lt; listeners.length, i++){
    listeners[i]()
  }

  return action
}

function replaceReducer(nextReducer){
  if(typeof nextReducer !== 'function'){
    throw new Error('Expected the nextReducer to be a function')
  }

  currentReducer = nextReducer
  dispatch({type:ActionTYpes.INIT})
}

### combineReudcers(reducers)

`</pre>

import { combineReducers } from 'redux'
import counterReducer from './counterReducer'
import todosReducer from './todosReducer'

const rootReducer = combineReducers({
  counter: counterReducer,   // &lt;--- 键名是 state 中的属性, 键值是对应 reducer 函数名

  todos: todosReducer
})
export default rootReducer

<pre>`
如果提高需求
`</pre>

state
  ├── counter: 0
  ├── todo
        ├── optTime: []
        ├── todoList: [] # 这其实就是原来的 todos!

<pre>`
对应的 reducers 是:
`</pre>

reducers/
   ├── index.js &lt;-------------- combineReducers (生成 rootReducer)
   ├── counterReducer.js
   ├── todoReducers/ &lt;--------- combineReducers
           ├── index.js
           ├── optTimeReducer.js
           ├── todoListReducer.js

<pre>`
`</pre>

/*  reducers/index.js */
import { combineReducers } from 'redux'
import counterReducer from './counterReducer'
import todosReducers from './todosReducer'

const rootReducer = combineReducers({
  counter: counterReducer,
  todos: todosReducers
})

export default rootReducer

=================================================

/* reducers/todosReducers/index.js */

import { combineReducers } from 'redux'
import optTimeReducer from './optTimeReducer'
import todoListReducer from './todoListReducer'

const todosReducers = combineReducers({
  optTime: optTimeReducer,
  todoList: todoListReducer
})

export default todosReducers

<pre>`
无论 dispatch 哪个 action 都会流通**所有** reducer, 但是由于 reducer 是纯函数, 效率还是会提高.

### BindActionCreator

### applyMiddlware(...middlewares)

先要理解 Middleware, enhancer

Redux 引入中间件机制是为了在 dispatch 前后进行处理

`</pre>

const printStateMiddleware = ({getState}) => next => action => {
  console.log('...')
  let returnValue = next(action)
  console.log('...')
  return returnValue
}

<pre>`
实际上最内层
`</pre>

function printStateMiddleware(middlewareAPI){ //中间件内可以使用的 API, 如 getState 与 dispatch
   return function(dispatch){ // 传入原 dispatch 的引用
    return function(action){
      console.log(...)
      var returnValue = dispatch(action)  //  执行 dispatch 行为, dispatch(action) 返回的还是 action
      console.log(...)
      return returnValue // 传给下一个中间件的 action
    }
   }
}

<pre>`
### Store Enhancer

说白了 Store Enhancer 是对生成 store 的 API 的改造, 与 middleware 的最大区别是 middlewere 不修改 store 的 API

改造 store 的 API 就要从 createStore 入口

Redux 的 applyMiddleware 就是一个 Enhancer

`</pre>

import compose from './compose' // 作用就是层层包裹

// 传入中间件
export default function applyMiddleware(...middlewares){
  // 传入 createStore
  return function(createStore){
    // 返回一个函数签名和 createStore 一样的函数, 即返回一个增强版的 createStore
    return function(reducer, preloadState, enhancer){
      // 用原 createStore 先生成一个 store, 包含 getState, dispatch, subscribe, replaceReducer 四个 API
      var store = creataStore(reducer, preloadState, enhancer)

<pre>`  var dispatch = store.dispatch //  生成指向原 dispatch的引用
  var chain = [] // 存储中间件的数组

  //提供给中间件的 API 其实就是 store 的 API
  var middlewareAPI = {
    getState: store.getStore,
    dispatch: (action) =&gt; dispatch(action)
  }

  // 给中间件添加 API
  chain = middlewares.map(middleware =&gt; middleware(middlewareAPI))

  // 串联中间件, 添加中间件的起点 store.dispatch, 返回经过修饰的 dispatch
  dispatch = compose(...middlewares)(store.dispatch)

  return{
    ...store, // store 中保留的原 API
     dispatch  // 用新的 dispatch 覆盖原 dispatch
  }
}

}
}

1
[参考](https://cnodejs.org/topic/57bd23ee1d27b9113348a546)