整理一下JavaScript中的数组方法reduce的学习知识

1,018 阅读2分钟

介绍

The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in single output value (mdn介绍)

这么一看似乎看起来很懵,我也是这样 然后就有了下面的学习记录

基本使用

[1, 2, 3, 4].reduce((pre, cur) => {
  return pre + cur;
})

这是一个入门都会学的一个东西 数组求和 归纳函数每次归纳数组中的每一项(cur),然后将计算结果返回给累加器(pre), 然后反复迭代和归纳,将最后的结果(pre)返回回去,这样就到达了数组求和的目的。

多一个参数

[1, 2, 3, 4].reduce((pre, cur) => {
  return pre + cur;
}, 5)

多加了一个参数之后初始的pre值会根据reduce的第二个参数初始化

画个图理解一下

pre被第二个参数初始化 然后cur不断移动 然后不断赋值给pre 直到遍历到最后 然后返回,如果没有传入初始化的的函数的话 pre会被初始化数组的第一个元素,然后cur指向下一个

理解不如手写

自己简写的

Array.prototype.myReduce = function (callback /*, initialValue */) {
  var arr = this,
    len = arr.length,
    value = arguments[1] || arr[0];

  var init = arguments[1] ? 0 : 1;
  for (var i = init; i < len; i++) {
    value = callback(value, arr[i], i, arr);
  }
  return value;
};

MDN的Polyfill

if (!Array.prototype.reduce) {
  Object.defineProperty(Array.prototype, "reduce", {
    value: function (callback, initialValue) {
      if (this === null) {
        throw new TypeError(
          "Array.prototype.reduce called on null or undefined"
        );
      }
      if (typeof callback !== "function") {
        throw new TypeError(callback + "is not a function");
      }
      var o = Object(this);
      var len = o.length >>> 0;
      var k = 0;
      var value;

      if (arguments.length >= 2) {
        value = arguments[1];
      } else {
        while (k < len && !(k in o)) {
          k++;
        }
        if (k >= len) {
          throw new TypeError("reduce of empty array with no initial value");
        }
        value = o[k++];
      }

      while (k < len) {
        if (k in o) {
          value = callback(value, o[k], k, o);
        }
        k++;
      }
      return value;
    },
  });
}

MD的更加严谨 大家可以看我的理解一下 然后直接看官方的 这样能更好的理解

简单应用

扁平化数组

var arr = [1, 2, 3, 4, 5, ["zhangsna", "lisi", ["ss", "ss", ["ss", "ss"]]]];

function arrFlat(arr) {
  return arr.reduce(function (pre, cur) {
    // return pre.concat(Object.prototype.toString.call(cur) === '[object Array]'?arrFlat(cur):cur)

    if (Object.prototype.toString.call(cur) === '[object Array]') {
      return [...pre, ...arrFlat(cur)]
    } else {
      return [...pre, cur]
    }

  }, [])
}

console.log(arrFlat(arr))

组合函数

function toUpper(s) {
  return s.toUpperCase();
}

function exclaim(str) {
  return str + "!";
}

function exclaim1(str) {
  return str + "?";
}

// compose组合函数

// reduce
function compose(...args) {
  if (args.length === 0) return a => a;
  if (args.length === 1) return args[0];
  return args.reduce((pre, cur) => x => pre(cur(x)));
}

// reduceRight
function compose(...args) {
  if (args.length === 0) return a => a;
  if (args.length === 1) return args[0];
  return x => args.reduceRight((res, cb) => cb(res), x);
}
// 大家体会一下用reduce和reduceRight的不一样的地方 两者实现函数的组合有一定的差别

reudx

大家用过React的话一定使用过redux吧 redux也是用reduce实现的,我给出我学习过程中的reudx的简单源码实现,大家可以看看更厉害的人写出来的源码分析 createStore.js

function createStore(reducer, enhancer) {
  if (enhancer) {
    return enhancer(createStore)(reducer);
  }
  let currentState = undefined;
  let currentListeners = [];
  function getState() {
    return currentState;
  }
  function dispatch(action) {
    currentState = reducer(currentState, action);
    currentListeners.forEach((item) => {
      item();
    });
  }
  function subscribe(callback) {
    currentListeners.push(callback);
  }

  dispatch({ type: '@INIT' });
  return {
    getState,
    dispatch,
    subscribe,
  };
}

applyMiddleware.js

function applyMiddleware(...middlewares) {
  return (createStore) => (...args) => {
    var store = createStore(...args);
    let dispatch = store.dispatch;
    var middleApi = {
      getState: store.getState,
      dispatch: (action) => dispatch(action),
    };
    var middlewaresChain = middlewares.map((middleware) =>
      middleware(middleApi)
    );
    dispatch = compose(...middlewaresChain)(store.dispatch);
    return {
      ...store,
      dispatch,
    };
  };
}

compose.js

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)));
}

以上就是我学习过程中学过的reduce知识,整理了一下,希望您看了会有收获!!