function createStore(reducer) { let state = reducer(undefined, {}); //стартовая инициализация состояния, запуск редьюсера со state === undefined let cbs = []; //массив подписчиков const getState = () => state; //функция, возвращающая переменную из замыкания const subscribe = (cb) => ( cbs.push(cb), //запоминаем подписчиков в массиве () => (cbs = cbs.filter((c) => c !== cb)) ); //возвращаем функцию unsubscribe, которая удаляет подписчика из списка const dispatch = (action) => { if (typeof action === "function") { //если action - не объект, а функция return action(dispatch, getState); //запускаем эту функцию и даем ей dispatch и getState для работы } const newState = reducer(state, action); //пробуем запустить редьюсер if (newState !== state) { //проверяем, смог ли редьюсер обработать action state = newState; //если смог, то обновляем state for (let cb of cbs) cb(); //и запускаем подписчиков } }; return { getState, //добавление функции getState в результирующий объект dispatch, subscribe, //добавление subscribe в объект }; } function countReducer(state = {count: 0}, {type}){ if(type === "COUNT_INC"){ return { count: state.count + 1 } } if(type === "COUNT_DEC"){ return { count: state.count - 1 } } return state } function localStoreReducer (reducer, localStorageKey){ function localStoredReducer (state, action){ // Если state === undefined, то достать старый state из local storage if(state === undefined){ try { return JSON.parse(localStorage[localStorageKey]) } catch(e){} } const newState = reducer(state, action) // Сохранить newState в local storage localStorage[localStorageKey] = JSON.stringify(newState) return newState } return localStoredReducer } const store = createStore(localStoreReducer(countReducer, 'count')) store.subscribe( () => console.log(store.getState()) ) store.dispatch({type: "COUNT_INC"}) store.dispatch({type: "COUNT_INC"}) store.dispatch({type: "COUNT_DEC"})