程序笔记   发布时间:2019-11-07  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Redux源码学习笔记大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

https://github.com/reduxjs/redux 版本 4.0.0

先了解一下redux是怎么用的,此处摘抄自阮一峰老师的《

<span style="color: #008000;">//<span style="color: #008000;"> store 是保存数据的地方

<span style="color: #008000;">//<span style="color: #008000;"> 创建 store
import { createStore } from 'redux'<span style="color: #000000;">
const store =<span style="color: #000000;"> createStore(fn)

<span style="color: #008000;">//<span style="color: #008000;"> state 是某一时刻 store 的快照,一个 state 对应一个 view<span style="color: #008000;">
//<span style="color: #008000;"> 可通过 getState() 获取
const state =<span style="color: #000000;"> store.getState()

<span style="color: #008000;">//<span style="color: #008000;"> Action 是一个对象 用来表示 view 发出的改变 state 的通知<span style="color: #008000;">
//<span style="color: #008000;"> type 是必须的 其他属性可以自由设置
const action =<span style="color: #000000;"> {
type: 'ADD_TODO'<span style="color: #000000;">,payload: 'Learn Redux'<span style="color: #000000;">
}

<span style="color: #008000;">//<span style="color: #008000;"> 同一种类型的 action 可以写一个函数生成
const ADD_TODO = '添加 TODO'
<span style="color: #008000;">//<span style="color: #008000;"> 生成 action 的函数: Action Creator
<span style="color: #0000ff;">function<span style="color: #000000;"> addTodo(text) {
<span style="color: #0000ff;">return<span style="color: #000000;"> {
type: ADD_TODO,text
}
}

const action = addTodo('Learn Redux'<span style="color: #000000;">)

<span style="color: #008000;">//<span style="color: #008000;"> store.dispatch()是 View 发出 Action 的唯一方法。
<span style="color: #000000;">store.dispatch(action)

<span style="color: #008000;">//<span style="color: #008000;"> reducer 是 store 接收 state 返回新的 state 的过程
<span style="color: #000000;">
const defaultState = 0
<span style="color: #008000;">//<span style="color: #008000;"> reducer 接收 action 返回新的 state
const reducer = (state = defaultState,action) =><span style="color: #000000;"> {
<span style="color: #0000ff;">switch<span style="color: #000000;">(action.type) {
<span style="color: #0000ff;">case: 'ADD'<span style="color: #000000;">:
<span style="color: #0000ff;">return state +<span style="color: #000000;"> action.payload
<span style="color: #0000ff;">default<span style="color: #000000;">:
<span style="color: #0000ff;">return<span style="color: #000000;"> state
}
}
const state = reducer(1<span style="color: #000000;">,{
type: 'ADD'<span style="color: #000000;">,payload: 2<span style="color: #000000;">
})

<span style="color: #008000;">//<span style="color: #008000;"> 创建 store 时传入 reducer 当调用 store.dispatch 时将自动调用 reducer
const store =<span style="color: #000000;"> createStore(reducer)

<span style="color: #008000;">/*<span style="color: #008000;">
reducer 是一个纯函数,纯函数要求:

  • 不得改写参数
  • 不能调用系统 I/O 的API
  • 不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果
    <span style="color: #008000;">*/

<span style="color: #008000;">//<span style="color: #008000;"> store.subscribe方法设置监听函数,一旦 State 发生变化,就自动执行这个函数<span style="color: #008000;">
//<span style="color: #008000;"> 返回解除监听函数
let unsubscribe = store.subsribe(() =><span style="color: #000000;"> { console.log(store.getState) })
unsubscribe() <span style="color: #008000;">//<span style="color: #008000;"> 解除监听

<span style="color: #008000;">/*<span style="color: #008000;">
store 提供的三个方法

  • store.getState()
  • store.dispatch()
  • store.subscribe()
    <span style="color: #008000;">*/

<span style="color: #008000;">//<span style="color: #008000;"> createStore方法还可以接受第二个参数,表示 State 的最初状态。这通常是服务器给出的。<span style="color: #008000;">
//<span style="color: #008000;"> !这个初始值会覆盖 Reducer 函数默认的初始值
let store =<span style="color: #000000;"> createStore(todoApp,STATE_FROM_SERVER)

<span style="color: #008000;">//<span style="color: #008000;"> createStore 的简单实现
const createStore = (reducer) =><span style="color: #000000;"> {
let state
let listeners =<span style="color: #000000;"> []

const getState </span>= () =><span style="color: #000000;"&gt; state

const dispatch </span>= action =><span style="color: #000000;"&gt; {
    state </span>=<span style="color: #000000;"&gt; reducer(state,action)
    listeners.forEach(listener </span>=><span style="color: #000000;"&gt; listener())
}

const subscribe </span>= listener =><span style="color: #000000;"&gt; {
    listeners.push(listener)
    </span><span style="color: #0000ff;"&gt;return</span> () =><span style="color: #000000;"&gt; {
        listeners </span>= listeners.filter(l => l !==<span style="color: #000000;"&gt; listener)
    }
}

dispatch({})

</span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; { getState,dispatch,subscribe }

}

<span style="color: #008000;">//<span style="color: #008000;"> 可以通过 combineReducers 来将多个 Reducer 合为一个
import { combineReducers } from 'redux'<span style="color: #000000;">

const chatReducer =<span style="color: #000000;"> combineReducers({
chatLog,statusMessage,userName
})

<span style="color: #008000;">//<span style="color: #008000;"> combineReducer 的简单实现
const combineReducers = reducers =><span style="color: #000000;"> {
<span style="color: #0000ff;">return (state = {},action) =><span style="color: #000000;">
Object.keys(reducers).reduce(
(nextState,key) =><span style="color: #000000;"> {
nextState[key] =<span style="color: #000000;"> reducers
key
<span style="color: #0000ff;">return<span style="color: #000000;"> nextState
},{}
)
}

工作流程

dispatch(action) (previousState,action)

Action Creators ======> Store ======><span style="color: #000000;"> Reducers
^ || <======<span style="color: #000000;">
_ ||<span style="color: #000000;"> (newStatE)
_ (statE) ||<span style="color: #000000;">
_ ||<span style="color: #000000;">
(view opt)_ \/<span style="color: #000000;">
\--- React Comonents

OK 可以开始看源码了~ 网上Redux源码分析的博客真的非常多.. 不过当你知道他的源码究竟有多短 就能理解了hhh 

combineReducers.js 

代码一共179行 多是错误处理 我先将错误处理全部删掉 便只剩28行.....

思路就是创建一个对象 将 Reducer 全部放进去

当Action传进来的时候 就让每一个Reducer去处理这个action

每个Reducer都有一个对应的key 只处理state中对应字段 state[key] 没有Reducer对应的字段会被忽略

截取出核心代码 + 用法、感觉并不需要注释、逻辑都很直接

{ const reducerKeys =ject.keys(reducers) const finalReducers ={} (let i = 0; i < reducerKeys.length; i++{ const key =</span><span style="color: #0000ff;"&gt;if</span> (<span style="color: #0000ff;"&gt;typeof</span> reducers[key] === 'function'<span style="color: #000000;"&gt;) { finalReducers[key] </span>=<span style="color: #000000;"&gt; reducers[key] }

}
const finalReducerKeys =<span style="color: #000000;"> Object.keys(finalReducers)

<span style="color: #0000ff;">return <span style="color: #0000ff;">function combination(state =<span style="color: #000000;"> {},action) {
let hasChanged = <span style="color: #0000ff;">false<span style="color: #000000;">
const nextState =<span style="color: #000000;"> {}
<span style="color: #0000ff;">for (let i = 0; i < finalReducerKeys.length; i++<span style="color: #000000;">) {
const key =<span style="color: #000000;"> finalReducerKeys[i]
const reducer =<span style="color: #000000;"> finalReducers[key]
const previousStateForKey =<span style="color: #000000;"> state[key]
const nextStateForKey =<span style="color: #000000;"> reducer(previousStateForKey,action)

  nextState[key] </span>=<span style="color: #000000;"&gt; nextStateForKey
  hasChanged </span>= hasChanged || nextStateForKey !==<span style="color: #000000;"&gt; previousStateForKey
}
</span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 如果state每一个key都没有被修改 就直接返回原state</span>
<span style="color: #0000ff;"&gt;return</span> hasChanged ?<span style="color: #000000;"&gt; nextState : state

}
}

<span style="color: #008000;">/*<span style="color: #008000;">**** 下面是简单的用法实例 ****<span style="color: #008000;">*/
<span style="color: #0000ff;">function todos(state =<span style="color: #000000;"> [],action) {
<span style="color: #0000ff;">switch<span style="color: #000000;"> (action.typE) {
<span style="color: #0000ff;">case 'ADD_TODO'<span style="color: #000000;">:
<span style="color: #0000ff;">return<span style="color: #000000;"> state.concat(action.text)
<span style="color: #0000ff;">default<span style="color: #000000;">:
<span style="color: #0000ff;">return<span style="color: #000000;"> state
}
}

<span style="color: #0000ff;">function counter(state = 0<span style="color: #000000;">,action) {
<span style="color: #0000ff;">switch<span style="color: #000000;"> (action.typE) {
<span style="color: #0000ff;">case 'INCREMENT'<span style="color: #000000;">:
<span style="color: #0000ff;">return state + 1
<span style="color: #0000ff;">case 'DECREMENT'<span style="color: #000000;">:
<span style="color: #0000ff;">return state - 1
<span style="color: #0000ff;">default<span style="color: #000000;">:
<span style="color: #0000ff;">return<span style="color: #000000;"> state
}
}

let reducer =<span style="color: #000000;"> combineReducers({ list: todos,number: counter })
let state = { list: [],number: 0,otherKey: 'no reducer match will be ignore'<span style="color: #000000;"> }
console.log(statE) <span style="color: #008000;">//<span style="color: #008000;"> { list: [],otherKey: 'no reducer match will be ignore' }
state = reducer(state,{ type: 'ADD_TODO',text: 'study'<span style="color: #000000;"> })
console.log(statE) <span style="color: #008000;">//<span style="color: #008000;"> { list: [ 'study' ],number: 0 }
state = reducer(state,text: 'sleep'<span style="color: #000000;"> })
console.log(statE) <span style="color: #008000;">//<span style="color: #008000;"> { list: [ 'study','sleep' ],{ type: 'INCREMENT'<span style="color: #000000;"> })
console.log(statE) <span style="color: #008000;">//<span style="color: #008000;"> { list: [ 'study',number: 1 }

s.js 源码

https://cn.js-code.com/res/2019/02-05/22/1c53668bcee393edac0d7b3b3daff1ae.gif" alt="">https://cn.js-code.com/res/2019/02-05/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
import ActionTypes from './utils/actionTypes''./utils/warning'ject from './utils/isPlainObject'

<span style="color: #0000ff;">function<span style="color: #000000;"> getUndefinedStateErrormessage(key,action) {
const actionType = action &&<span style="color: #000000;"> action.type
const actionDescription =<span style="color: #000000;">
(actionType && action "${String(actionTypE)}") || 'an action'

<span style="color: #0000ff;">return<span style="color: #000000;"> (
Given ${actionDescription},reducer </span>"${key}" returned undefined. +<span style="color: #000000;">
To ignore an action,you must explicitly </span><span style="color: #0000ff;"&gt;return</span> the previous state. +<span style="color: #000000;">
If you want </span><span style="color: #0000ff;"&gt;this</span> reducer to hold no value,you can <span style="color: #0000ff;"&gt;return</span> <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt; instead of undefined.
)
}

<span style="color: #0000ff;">function<span style="color: #000000;"> getUnexpectedStateShapeWarningmessage(
inputState,reducers,action,unexpectedKeyCache
) {
const reducerKeys =<span style="color: #000000;"> Object.keys(reducers)
const argumentName =<span style="color: #000000;">
action && action.type ===<span style="color: #000000;"> ActionTypes.INIT
? 'preloadedState argument passed to createStore'<span style="color: #000000;">
: 'previous state received by the reducer'

<span style="color: #0000ff;">if (reducerKeys.length === 0<span style="color: #000000;">) {
<span style="color: #0000ff;">return<span style="color: #000000;"> (
'Store does not have a valid reducer. Make sure the argument passed ' +
'to combineReducers is an object whose values are reducers.'<span style="color: #000000;">
)
}

<span style="color: #0000ff;">if (!<span style="color: #000000;">isPlainObject(inputStatE)) {
<span style="color: #008000;">//<span style="color: #008000;"> 希望 inputState 是一个简单对象:通过 new Object() 、 {} 创建 (Object.create(null) 这里好像是不合法的
<span style="color: #008000;">//<span style="color: #008000;"> [object Array] 中提取 'Array'
<span style="color: #008000;">//<span style="color: #008000;"> Object.prototype.toString.call(inputStatE).match(/\s([a-z|A-Z]+)/)[1]
<span style="color: #0000ff;">return<span style="color: #000000;"> (
The ${argumentNamE} has unexpected type of </span>"<span style="color: #000000;"&gt; +
{}.toString.call(inputStatE).match(/\s([a-z|A-Z]+)/)[1] +
</span>". Expected argument to be an object <span style="color: #0000ff;"&gt;with</span> the following +<span style="color: #000000;">
keys: </span>"${reducerKeys.join('","')}"<span style="color: #000000;"&gt;
)
}
<span style="color: #008000;">//<span style="color: #008000;"> 检查所有Reducer都没有处理到的key ( 此处实在不解 unexpectedKeyCache 到底何用= =
const unexpectedKeys =<span style="color: #000000;"> Object.keys(inputStatE).filter(
key => !reducers.hasOwnProperty(key) && !<span style="color: #000000;">unexpectedKeyCache[key]
)

unexpectedKeys.forEach(key =><span style="color: #000000;"> {
unexpectedKeyCache[key] = <span style="color: #0000ff;">true<span style="color: #000000;">
})
<span style="color: #008000;">//<span style="color: #008000;"> 替换 store 的 Reducer 时会调用 dispatch({ type: ActionTypes.replaCE })
<span style="color: #0000ff;">if (action && action.type === ActionTypes.replaCE) <span style="color: #0000ff;">return

<span style="color: #0000ff;">if (unexpectedKeys.length > 0<span style="color: #000000;">) {
<span style="color: #0000ff;">return<span style="color: #000000;"> (
Unexpected ${unexpectedKeys.length </span>> 1 ? 'keys' : 'key'} +<span style="color: #000000;">
</span>"${unexpectedKeys.join('","')}" found <span style="color: #0000ff;"&gt;in</span> ${argumentNamE}. +<span style="color: #000000;">
Expected to find one of the known reducer keys instead: +<span style="color: #000000;">
</span>"${reducerKeys.join('","')}"<span style="color: #000000;"&gt;. Unexpected keys will be ignored.
)
}
}

<span style="color: #0000ff;">function<span style="color: #000000;"> assertReducerShape(reducers) {
Object.keys(reducers).forEach(key =><span style="color: #000000;"> {
const reducer =<span style="color: #000000;"> reducers[key]
const initialState =<span style="color: #000000;"> reducer(undefined,{ type: ActionTypes.INIT })
<span style="color: #008000;">//<span style="color: #008000;"> Reducer"$ {key}"在初始化时返回undefined。如果传递给reducer的状态未定义,你必须明确返回初始状态。
<span style="color: #008000;">//<span style="color: #008000;"> 初始状态可以是不可定义。如果你不想为这个reducer设置一个值,你可以使用Null而不是undefined。
<span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof initialState === 'undefined'<span style="color: #000000;">) {
<span style="color: #0000ff;">throw <span style="color: #0000ff;">new<span style="color: #000000;"> Error(
Reducer </span>"${key}" returned undefined during initialization. +<span style="color: #000000;">
If the state passed to the reducer is undefined,you must +<span style="color: #000000;">
explicitly </span><span style="color: #0000ff;"&gt;return</span> the initial state. The initial state may +<span style="color: #000000;">
not be undefined. If you don</span>'<span style="color: #000000;"&gt;t want to set a value for this reducer, +
you can use null instead of undefined.
)
}

if (
  typeof reducer(undefined,{
    type: ActionTypes.PROBE_UNKNOWN_ACTION()
  }) === </span>'undefined'<span style="color: #000000;"&gt;
) {
  // 当使用随机类型探测Reducer${key}时返回undefined。
  // 不要试图处理${ActionTypes.INIT}或者其他在"redux/*"命名空间的动作。它们被认为是私有的。
  // 相反,当你遇到任何未知动作时,你必须返回当前的state,除非当前state是undefined,
  // 那样你要返回初始状态,而不管动作类型。初始状态不可以是undefined,但可以为null
  throw new Error(
    `Reducer "${key}" returned undefined when probed with a random type. ` +
      `Don</span>'t <span style="color: #0000ff;"&gt;try</span><span style="color: #000000;"&gt; to handle ${
        ActionTypes.INIT
      } or other actions </span><span style="color: #0000ff;"&gt;in</span> "redux/*" ` +<span style="color: #000000;"&gt;
      `namespace. They are considered private. Instead,you must </span><span style="color: #0000ff;"&gt;return</span> the ` +<span style="color: #000000;"&gt;
      `current state </span><span style="color: #0000ff;"&gt;for</span> any unknown actions,unless it is undefined,` +<span style="color: #000000;"&gt;
      `</span><span style="color: #0000ff;"&gt;in</span> which <span style="color: #0000ff;"&gt;case</span> you must <span style="color: #0000ff;"&gt;return</span> the initial state,regardless of the ` +<span style="color: #000000;"&gt;
      `action type. The initial state may not be undefined,but can be </span><span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;.`
  )
}

})
}

<span style="color: #008000;">/<span style="color: #008000;">

  • Turns an object whose values are different reducer functions,into a single

  • reducer function. It will call every child reducer,and gather their results

  • into a single state object,whose keys correspond to the keys of the passed

  • reducer functions.

  • @param {Object} reducers An object whose values correspond to different

  • reducer functions that need to be combined into one. One hAndy way to obtain

  • it is to use ES6 import * as reducers syntax. The reducers may never return

  • undefined for any action. Instead,they should return their initial state

  • if the state passed to them was undefined,and the current state for any

  • unrecognized action.

  • @returns {Function} A reducer function that invokes every reducer inside the

  • passed object,and builds a state object with the same shape.
    <span style="color: #008000;">*/<span style="color: #000000;">
    export <span style="color: #0000ff;">default <span style="color: #0000ff;">function<span style="color: #000000;"> combineReducers(reducers) {
    const reducerKeys =<span style="color: #000000;"> Object.keys(reducers)
    const finalReducers =<span style="color: #000000;"> {}
    <span style="color: #0000ff;">for (let i = 0; i < reducerKeys.length; i++<span style="color: #000000;">) {
    const key =<span style="color: #000000;"> reducerKeys[i]

    <span style="color: #0000ff;">if (process.env.NODE_ENV !== 'production'<span style="color: #000000;">) {
    <span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof reducers[key] === 'undefined'<span style="color: #000000;">) {
    warning(No reducer provided </span><span style="color: #0000ff;"&gt;for</span> key "${key}"<span style="color: #000000;"&gt;)
    }
    }

    <span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof reducers[key] === 'function'<span style="color: #000000;">) {
    finalReducers[key] =<span style="color: #000000;"> reducers[key]
    }
    }
    const finalReducerKeys =<span style="color: #000000;"> Object.keys(finalReducers)

let unexpectedKeyCache
<span style="color: #0000ff;">if (process.env.NODE_ENV !== 'production'<span style="color: #000000;">) {
unexpectedKeyCache =<span style="color: #000000;"> {}
}

let shapeAssertionError
<span style="color: #0000ff;">try<span style="color: #000000;"> {
<span style="color: #008000;">//<span style="color: #008000;"> 判断每个reducer都有初始值和对于未知action返回原state
<span style="color: #000000;"> assertReducerShape(finalReducers)
} <span style="color: #0000ff;">catch<span style="color: #000000;"> (E) {
shapeAssertionError =<span style="color: #000000;"> e
}

<span style="color: #0000ff;">return <span style="color: #0000ff;">function combination(state =<span style="color: #000000;"> {},action) {
<span style="color: #0000ff;">if<span style="color: #000000;"> (shapeAssertionError) {
<span style="color: #0000ff;">throw<span style="color: #000000;"> shapeAssertionError
}

</span><span style="color: #0000ff;"&gt;if</span> (process.env.NODE_ENV !== 'production'<span style="color: #000000;"&gt;) {
  const warningmessage </span>=<span style="color: #000000;"&gt; getUnexpectedStateShapeWarningmessage(
    state,finalReducers,unexpectedKeyCache
  )
  </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; (warningmessagE) {
    warning(warningmessagE)
  }
}

let hasChanged </span>= <span style="color: #0000ff;"&gt;false</span><span style="color: #000000;"&gt;
const nextState </span>=<span style="color: #000000;"&gt; {}
</span><span style="color: #0000ff;"&gt;for</span> (let i = 0; i < finalReducerKeys.length; i++<span style="color: #000000;"&gt;) {
  const key </span>=<span style="color: #000000;"&gt; finalReducerKeys[i]
  const reducer </span>=<span style="color: #000000;"&gt; finalReducers[key]
  const previousStateForKey </span>=<span style="color: #000000;"&gt; state[key]
  const nextStateForKey </span>=<span style="color: #000000;"&gt; reducer(previousStateForKey,action)
  </span><span style="color: #0000ff;"&gt;if</span> (<span style="color: #0000ff;"&gt;typeof</span> nextStateForKey === 'undefined'<span style="color: #000000;"&gt;) {
    const errormessage </span>=<span style="color: #000000;"&gt; getUndefinedStateErrormessage(key,action)
    </span><span style="color: #0000ff;"&gt;throw</span> <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; Error(errormessagE)
  }
  nextState[key] </span>=<span style="color: #000000;"&gt; nextStateForKey
  hasChanged </span>= hasChanged || nextStateForKey !==<span style="color: #000000;"&gt; previousStateForKey
}
</span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 如果state每一个key都没有被修改 就直接返回原state</span>
<span style="color: #0000ff;"&gt;return</span> hasChanged ?<span style="color: #000000;"&gt; nextState : state

}
}

s.js

可以参0-9a-z' 的随机字符串 const randomString = () =>String(36String(7'''.' const ActionTypes ={ INIT: `@@redux/INIT${randomString()}`,replaCE: `@@redux/replaCE${randomString()}`,PROBE_UNKNOWN_ACTION: () => `@@redux/PROBE_UNKNOWN_ACTION${randomString()}` export <span style="color: #0000ff;">default ActionTypes

是redux核心代码,不过这个没有什么难理解的地方

import $$observable from 'symbol-observable'import ActionTypes from './utils/actionTypes'<span style="color: #000000;">
import isPlainObject from './utils/isPlainObject'

<span style="color: #008000;">//<span style="color: #008000;"> 创建 store 的函数<span style="color: #008000;">
//<span style="color: #008000;"> preloadedState: store设置的初始值 这个值会覆盖 Reducer 的默认值<span style="color: #008000;">
//<span style="color: #008000;"> 如果使用了 combineReducers preloadedState 要和 combineReducers 有相同的keys<span style="color: #008000;">
//<span style="color: #008000;"> enhancer: 中间件
export <span style="color: #0000ff;">default <span style="color: #0000ff;">function<span style="color: #000000;"> createStore(reducer,preloadedState,enhancer) {
<span style="color: #008000;">//<span style="color: #008000;"> preloadedState可以不传 判断preloadedState是否存在
<span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof preloadedState === 'function' && <span style="color: #0000ff;">typeof enhancer === 'undefined'<span style="color: #000000;">) {
enhancer =<span style="color: #000000;"> preloadedState
preloadedState =<span style="color: #000000;"> undefined
}

<span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof enhancer !== 'undefined'<span style="color: #000000;">) {
<span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof enhancer !== 'function'<span style="color: #000000;">) {
<span style="color: #0000ff;">throw <span style="color: #0000ff;">new Error('Expected the enhancer to be a function.'<span style="color: #000000;">)
}
<span style="color: #008000;">//<span style="color: #008000;"> enhancer是一个高阶函数 调用enhancer返回一个"加强版"的createStore
<span style="color: #0000ff;">return<span style="color: #000000;"> enhancer(createStorE)(reducer,preloadedStatE)
}

<span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof reducer !== 'function'<span style="color: #000000;">) {
<span style="color: #0000ff;">throw <span style="color: #0000ff;">new Error('Expected the reducer to be a function.'<span style="color: #000000;">)
}

let currentReducer =<span style="color: #000000;"> reducer
let currentState =<span style="color: #000000;"> preloadedState
let currentListeners =<span style="color: #000000;"> []
let nextListeners =<span style="color: #000000;"> currentListeners
let isDispatching = <span style="color: #0000ff;">false
<span style="color: #008000;">//<span style="color: #008000;"> 判断当前 nextListeners 和 currentListeners 是否为同一个对象
<span style="color: #008000;">//<span style="color: #008000;"> 如果是一个对象 就把 nextListeners 改为 currentListeners 的副本
<span style="color: #0000ff;">function<span style="color: #000000;"> ensureCanMutateNextListeners() {
<span style="color: #0000ff;">if (nextListeners ===<span style="color: #000000;"> currentListeners) {
nextListeners =<span style="color: #000000;"> currentListeners.slice()
}
}
<span style="color: #008000;">//<span style="color: #008000;"> 获取当前对象 如果是正在派发action 则不能获取state
<span style="color: #0000ff;">function<span style="color: #000000;"> getState() {
<span style="color: #0000ff;">if<span style="color: #000000;"> (isDispatching) {
<span style="color: #0000ff;">throw <span style="color: #0000ff;">new<span style="color: #000000;"> Error(
'You may not call store.getState() while the reducer is execuTing. ' +
'The reducer has already received the state as an argument. ' +
'Pass it down from the top reducer instead of reading it from the store.'<span style="color: #000000;">
)
}

</span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; currentState

}
<span style="color: #008000;">//<span style="color: #008000;"> 订阅 添加订阅者
<span style="color: #0000ff;">function<span style="color: #000000;"> subscribe(listener) {
<span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof listener !== 'function'<span style="color: #000000;">) {
<span style="color: #0000ff;">throw <span style="color: #0000ff;">new Error('Expected the listener to be a function.'<span style="color: #000000;">)
}

</span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; (isDispatching) {
  </span><span style="color: #0000ff;"&gt;throw</span> <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; Error(
    </span>'You may not call store.subscribe() while the reducer is execuTing. ' +
      'If you would like to be notified after the store has been updated,subscribe from a ' +
      'component and invoke store.getState() in the callBACk to access the latest state. ' +
      'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.'<span style="color: #000000;"&gt;
  )
}

let isSubscribed </span>= <span style="color: #0000ff;"&gt;true</span>
<span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 每次修改 nextListeners 都要判断一下 nextListeners 和 currentListeners 是否为同一个对象</span>

<span style="color: #000000;"> ensureCanMutateNextListeners()
<span style="color: #008000;">//<span style="color: #008000;"> 注意 这里修改 nextListeners 之后并没有改变 currentListeners 而是在下一次用到 currentListeners 才会改变
<span style="color: #000000;"> nextListeners.push(listener)

</span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 返回一个当前监听者取消订阅的方法</span>
<span style="color: #0000ff;"&gt;return</span> <span style="color: #0000ff;"&gt;function</span><span style="color: #000000;"&gt; unsubscribe() {
  </span><span style="color: #0000ff;"&gt;if</span> (!<span style="color: #000000;"&gt;isSubscribed) {
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt;
  }
  </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 正在派发 action 时不能进行操作</span>
  <span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; (isDispatching) {
    </span><span style="color: #0000ff;"&gt;throw</span> <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; Error(
      </span>'You may not unsubscribe from a store listener while the reducer is execuTing. ' +
        'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.'<span style="color: #000000;"&gt;
    )
  }

  isSubscribed </span>= <span style="color: #0000ff;"&gt;false</span><span style="color: #000000;"&gt;

  ensureCanMutateNextListeners()
  const index </span>=<span style="color: #000000;"&gt; nextListeners.indexOf(listener)
  nextListeners.splice(index,</span>1<span style="color: #000000;"&gt;)
}

}

<span style="color: #0000ff;">function<span style="color: #000000;"> dispatch(action) {
<span style="color: #0000ff;">if (!<span style="color: #000000;">isPlainObject(action)) {
<span style="color: #0000ff;">throw <span style="color: #0000ff;">new<span style="color: #000000;"> Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'<span style="color: #000000;">
)
}

</span><span style="color: #0000ff;"&gt;if</span> (<span style="color: #0000ff;"&gt;typeof</span> action.type === 'undefined'<span style="color: #000000;"&gt;) {
  </span><span style="color: #0000ff;"&gt;throw</span> <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; Error(
    </span>'Actions may not have an undefined "type" property. ' +
      'Have you misspelled a constant?'<span style="color: #000000;"&gt;
  )
}

</span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; (isDispatching) {
  </span><span style="color: #0000ff;"&gt;throw</span> <span style="color: #0000ff;"&gt;new</span> Error('Reducers may not dispatch actions.'<span style="color: #000000;"&gt;)
}

</span><span style="color: #0000ff;"&gt;try</span><span style="color: #000000;"&gt; {
  </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 用 isDispatching 记录是否正在 派发action 过程中不能进行其他操作</span>
  isDispatching = <span style="color: #0000ff;"&gt;true</span><span style="color: #000000;"&gt;
  currentState </span>=<span style="color: #000000;"&gt; currentReducer(currentState,action)
} </span><span style="color: #0000ff;"&gt;finally</span><span style="color: #000000;"&gt; {
  isDispatching </span>= <span style="color: #0000ff;"&gt;false</span><span style="color: #000000;"&gt;
}
</span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 用到 listeners 才会修改 currentListeners 以减少修改次数</span>
const listeners = (currentListeners =<span style="color: #000000;"&gt; nextListeners)
</span><span style="color: #0000ff;"&gt;for</span> (let i = 0; i < listeners.length; i++<span style="color: #000000;"&gt;) {
  const listener </span>=<span style="color: #000000;"&gt; listeners[i]
  listener()
}

</span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; action

}

<span style="color: #008000;">//<span style="color: #008000;"> 替换 Reducer 并派发动作 ActionTypes.replaCE 相当于对state重新进行初始化
<span style="color: #0000ff;">function<span style="color: #000000;"> replaceReducer(nextReducer) {
<span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof nextReducer !== 'function'<span style="color: #000000;">) {
<span style="color: #0000ff;">throw <span style="color: #0000ff;">new Error('Expected the nextReducer to be a function.'<span style="color: #000000;">)
}

currentReducer </span>=<span style="color: #000000;"&gt; nextReducer
dispatch({ type: ActionTypes.replaCE })

}
<span style="color: #008000;">//<span style="color: #008000;"> emmmm...看不懂这个 可以参 https://distums.github.io/2017/03/19/observables-proposal-for-ecmascript/
<span style="color: #0000ff;">function<span style="color: #000000;"> observable() {
const outerSubscribe =<span style="color: #000000;"> subscribe
<span style="color: #0000ff;">return<span style="color: #000000;"> {
subscribe(observer) {
<span style="color: #0000ff;">if (<span style="color: #0000ff;">typeof observer !== 'object' || observer === <span style="color: #0000ff;">null<span style="color: #000000;">) {
<span style="color: #0000ff;">throw <span style="color: #0000ff;">new TypeError('Expected the observer to be an object.'<span style="color: #000000;">)
}

    </span><span style="color: #0000ff;"&gt;function</span><span style="color: #000000;"&gt; observeState() {
      </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; (observer.next) {
        observer.next(getState())
      }
    }

    observeState()
    const unsubscribe </span>=<span style="color: #000000;"&gt; outerSubscribe(observeStatE)
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; { unsubscribe }
  },[$$observable]() {
    </span><span style="color: #0000ff;"&gt;return</span> <span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;
  }
}

}

dispatch({ type: ActionTypes.INIT })

<span style="color: #0000ff;">return<span style="color: #000000;"> {
dispatch,subscribe,getState,replaceReducer,[$$observable]: observable
}
}

s.js

此处参http://imweb.io/topic/5a426d32a192c3b460fce354" target="_blank">mapStateToProps,mapDispatchToProps的使用姿势》

按注释