array.reduce的学习以及使用场景

  • Post author:
  • Post category:其他



数组的reduce方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值。


reducer 函数接收4个参数:

  • accumulator (acc) (累加器)
  • current Value (cur) (当前值)
  • current Index (idx) (当前索引)
  • source Array (src) (源数组)


你的 reducer 函数的返回值分配给累加器,其值在数组的每个迭代中被记住,并最后成为最终的单个结果值。


注意:

  • 1.回调函数第一次执行时,previousValue 和 currentValue 可以是一个值,如果 initialValue 在调用 reduce 时被提供,那么第一个 previousValue 等于 initialValue ,并且currentValue 等于数组中的第一个值;如果initialValue 未被提供,那么previousValue 等于数组中的第一个值,currentValue等于数组中的第二个值。
  • 2.如果数组为空并且没有提供initialValue, 会抛出TypeError 。如果数组仅有一个元素(无论位置如何)并且没有提供initialValue, 或者有提供initialValue但是数组为空,那么此唯一值将被返回并且callback不会被执行。


使用场景:

  • 1.数组求和、积:
[1,2,3,4].reduce((a, b) => a + b) // 10
[1,2,3].reduce(function(pre,cur,index,arr){return pre * cur}) // 6
复制代码
  • 2.数组扁平化:
function flattMap(arr) {
  return Array.isArray(arr)
    ? arr.reduce((acc, value) => [
      ...acc,
      ...flattMap(value)
    ], [])
    : [arr];
}
flattMap([1, [2, 3], 1]); // [1, 2, 3, 1]
复制代码
  • 3.对象过滤:
const pick = (obj, arr) => {
  return arr.reduce((acc, curr) => {
    if (curr in obj) {
      acc[curr] = obj[curr];
      return acc;
    }
  }, {})
}
pick({a: 1, b: 2}, ['a']) // { a: 1 }
复制代码
  • 4.对象取值:
const a = { b: { c: { d: 2 }}}

const get = (obj, arr) => {
  return arr.reduce((acc, curr) => {
    return acc ? acc[curr] : null
  }, obj)
}
get(a, ['b', 'c', 'd']) // 2
复制代码

实现reduce

Array.prototype.fakeReduce = function(fn, initialValue) {
  if (typeof fn !== 'function') {
    throw new TypeError('fn is not a function!');
  }
  // 保存原数组
  let initialArr = this;
  // 复制原数组
  let arr = [...initialArr];

  if (initialValue) arr.unshift(initialValue);
  let index, newValue;

  while (arr.length > 1) {
    index = initialArr.length - arr.length + 1;
    // 返回数组的前2项的计算结果
    newValue = fn.call(null, arr[0], arr[1], index, initialArr);
    // 将arr数组的前2项删除并将其计算结果推到arr数组的首部
    arr.splice(0, 2, newValue);
  }
  return newValue;
};
复制代码

转载于:https://juejin.im/post/5bb099c6e51d450e4f38e121