/** * createStore(reducer,preloadedState预存储状态,enhancer对store性能进行加强) * { *      getState,dispatch,subscribe * } */function createStore(reducer, preloadedState, enhancer) {  // 9,束缚reducer参数类型  if (typeof reducer !== "function")    throw new Error("reducer must be a function");  // 12判断enchancer是否传递,是否是一个函数  if (typeof enhancer !== "undefined") {    if (typeof enhancer !== "function") {      throw new Error("enhancer must be a function");    }    // redux中调用,传入createStore 并返回一个函数,返回reducer, preloadedState    return enhancer(createStore)(reducer, preloadedState);  }  // 1,sotre对象中存储的状态  var currentState = preloadedState;  // 6,寄存订阅者函数  var currentListeners = [];  //   2,获取状态  function getState() {    return currentState;  }  // 3用于触发action的办法  function dispatch(action) {    // 10,判断action是否是一个对象    if (!isPlainObject(action)) throw new Error("action必须是一个对象");    // 11,判断action中的type属性是否存在    if (typeof action.type === "undefined")      throw new Error("action对象中必须有type属性");    currentState = reducer(currentState, action); // 依据以后状态和action解决返回新的状态    // 7循环数组调用订阅者    for (let i = 0; i < currentListeners.length; i++) {      // 获取订阅者      var listener = currentListeners[i];      // 调用订阅者      listener();    }  }  // 5,订阅状态  function subscribe(listener) {    currentListeners.push(listener);  }  //   8 返回  return {    getState,    dispatch,    subscribe,  };}// 4// store.subscribe(() => {});// 判断参数是否是对象类型// 判断对象的以后原型对象是否和顶层原型对象雷同function isPlainObject(obj) {  // 排除根本数据类型和null  if (typeof obj !== "object" || obj === null) return false;  // 辨别数组和对象 原型对象比照的形式  var proto = obj;  // 获取最顶层的原型对象  while (Object.getPrototypeOf(proto) !== null) {    proto = Object.getPrototypeOf(proto);  }  return Object.getPrototypeOf(obj) === proto; // 返回true就是对象}function applyMiddleware(...middlewares) {  return function (createStore) {    return function (reducer, preloadedState) {      // 创立store,拿到store,给中间件传参      var store = createStore(reducer, preloadedState);      // 阉割版的 store      var middlewareAPI = {        getState: store.getState,        dispatch: store.dispatch,      };      // 调用中间件的第一层函数 传递阉割版的store对象,返回中间件函数内的外面两层函数      var chain = middlewares.map((middleware) => middleware(middlewareAPI));      //  中间件第二层参数传参,第三层就是dispath      var dispatch = compose(...chain)(store.dispatch);      // 返回一个增强版的store      return {        ...store,        dispatch,      };    };  };}function compose() {  var funcs = [...arguments];  console.log(funcs);  // 因为函数嵌套问题,执行程序尽管是logger再thunk,为了保障程序,要顺叙数组,先执行thunk第二层返回dispath,  return function (dispatch) {    for (var i = funcs.length - 1; i >= 0; i--) {      // 第一轮执行返回值返回是thunk外面的函数,他是logger须要的      dispatch = funcs[i](dispatch);    }    return dispatch;  };}// bindActionCreators函数  将action creator函数转换为可能触发action的函数function bindActionCreators(actionCreators, dispatch) {  // 创立一个对象用于返回,返回值是一个对象  // function increment(){  //   dispatch({type:'increment'})  // }  var boundActionCreators = {};  for (var key in actionCreators) {    // IIFE解决key变量不能保留的问题    (function (key) {      boundActionCreators[key] = function () {        dispatch(actionCreators[key]());      };    })(key);    // actionCreators[key]()  拿到increment函数,执行,返回action对象    // dispatch(actionCreators[key]())  dispatch action对象  }  return boundActionCreators;}// combineReducers组合小的reducer成为大的reducer,返回一个reducer函数function combineReducers(reducers) {  //  查看reducer类型 它必须是函数  var reducerKeys = Object.keys(reducers);  for (var i = 0; i < reducerKeys.length; i++) {    var key = reducerKeys[i];    if (typeof reducers[key] !== "function")      throw new Error("reducer必须是函数");  }  // 调用一个一个的小的reducer 将每一个小的reducer中返回的状态存储在一个新的大的对象中  return function (state, action) {    var nextState = {}; // 存储最新的状态    // 循环reducer拿到最新的状态    for (var i = 0; i < reducerKeys.length; i++) {      var key = reducerKeys[i];      var reducer = reducers[key];      var previousStateForKey = state[key];      nextState[key] = reducer(previousStateForKey, action);    }    console.log(nextState)    return nextState;  };}

测试代码

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title></head><body>    <button id='increment'>+1</button>    <span id='box'>0</span>    <button id='decrement'>-1</button>    <script src="myRedux.js"></script>    <script src="middlewares/logger.js"></script>    <script src="middlewares/thunk.js"></script>    <script>        function enhancer(createStore) {            return function (reducer, preloadedState) {                var store = createStore(reducer, preloadedState)                var dispatch = store.dispatch                function _dispatch(action) {                    if (typeof action === 'function') {                        return action(dispatch)                    }                    dispatch(action)                }                return {                    ...store,                    dispatch: _dispatch                }            }        }        function counterReducer(state, action) {            switch (action.type) {                case 'increment':                    return state + 1;                case 'decrement':                    return state - 1                default:                    return state            }        }        var rootReducer = combineReducers({            counter: counterReducer        })        // 1创立store        // const store = createStore(reducer, 0, enhancer)        const store = createStore(rootReducer, {            counter: 100        }, applyMiddleware(logger, thunk))        console.log(store)        store.subscribe(function () {            // 获取最新的状态            console.log(store.getState())            document.getElementById('box').innerHTML = store.getState().counter        })        var actions = bindActionCreators({            increment,            decrement        }, store.dispatch)        function increment() {            return {                type: 'increment'            }        }        function decrement() {            return {                type: "decrement"            }        }        // 获取加按钮        document.getElementById('increment').onclick = function () {            // 触发action            // store.dispatch(function (dispatch) {            //     setTimeout(function () {            //         dispatch({            //             type: 'increment'            //         })            //     }, 1000);            // })            //   代码执行程序  logger->thunk->reducer            // store.dispatch({            //     type: 'increment'            // })            actions.increment()        }        document.getElementById('decrement').onclick = function () {            // store.dispatch({            //     type: 'decrement'            // })            actions.decrement()        }    </script></body></html>