ES6之数组reduce()方法详解

前言

最近看项目代码的时候老是会见到数组的reduce方法刚开始没有太在意,因为知道该方法的大致用法,但是由于往后不断地学习,发现自己原来对这个方法的理解有误或者说理解不全面,为了保持我对学习的秉性——拒绝一知半解,今天特意花时间来全面的探究了一下这个方法,以下是对数组reduce()方法的介绍以及我的一些理解,希望能给大家带来帮助

一.reduce语法说明

方法介绍:

reduce() 方法对数组中的每个元素执行一个由我们提供的reducer函数,且该函数为升序执行,并将其结果汇总为单个返回值。

参数说明:

arr.reduce(callback(accumulator, currentValue[, currentIndex [, array]])[, initialValue]) 

第一个参数: callback函数

执行数组中每个值 (如果没有提供第二个参数 initialValue ,则第一个值除外)的函数,包含四个参数:

  • accumulator: 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)。
  • currentValue:数组中正在处理的元素。
  • currentIndex可选 :数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则从索引1起始。
  • array可选:调用reduce()的原数组

第二个参数: initialValue可选

作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 注意: 在没有初始值的空数组上调用 reduce 将报错。

这样看起来会有点蒙,其实就是两种情况:一种情况是给了第二个参数initialValue初始值;一种是没提供初始值。

执行机制:

reduce为数组中的每一个元素依次执行callback函数,不包括数组中被删除或从未被赋值的元素

回调函数第一次执行时,accumulator 和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。

值得注意的是: 如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。

举例:无初始值:

[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){return accumulator + currentValue;
}); 

执行上述代码,callback 被调用四次,每次调用的参数和返回值如下表:

callbackaccumulatorcurrentValuecurrentIndexarrayreturn value
first call011[0,1,2,3,4]1
second call122[0,1,2,3,4]3
third call333[0,1,2,3,4]6
fourth call644[0,1,2,3,4]10

由reduce返回的值将是最后一次回调返回值(10)

有初始值:

[0, 1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => 
{ return accumulator + currentValue; }, 10 );
// 提供初始值为 10 

执行上述代码,每次调用的参数和返回值如下表:

callbackaccumulatorcurrentValuecurrentIndexarrayreturn value
first call1000[0,1,2,3,4]10
second call1011[0,1,2,3,4]11
third call1122[0,1,2,3,4]13
fourth call1333[0,1,2,3,4]16
fifth call1644[0,1,2,3,4]20

这种情况下reduce()返回的值是20

二.用途

介绍几个常用的用法

1.求和

1.1 基本数据类型求和

var total = [ 0, 1, 2, 3 ].reduce(( acc, cur ) => acc + cur,0
);
// total6 

1.2 引用数据类型求和

let arr = [{value: 45,},{value: 88,},{value: 101,},
];
let newArr = arr.reduce((acc, cur) => {return acc+ cur.value;
}, 0);
console.log(newArr); //234 

2.扁平数组

2.1二维数组转一维数组(利用concat方法可以将传入的数组参数与当前数组拼接)

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
 ( acc, cur ) => acc.concat(cur),
 []
);
// [0, 1, 2, 3, 4, 5] 

2.2多维数组转一维

let flattened = [[1, [2, 8]], [3, 4, 9], [5, [6, 10]]]
function fn(arr) {return arr.reduce((acc, cur) => {return acc.concat(Array.isArray(cur) ? fn(cur) : cur);}, []);
}
const newArr = fn(flattened );
console.log(newArr); //[1, 2, 8, 3, 4, 9, 5, 6, 10] 

3.累加对象里的值

let sum = [{x: 1}, {x:2}, {x:3}].reduce((accumulator, currentValue) => accumulator + currentValue.x,0
);
console.log(sum) //6 

4.计算数组中每个元素出现的次数

const names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let countedNames = names.reduce(function (allNames, name) { if (name in allNames) {allNames[name]++;}else {allNames[name] = 1;}return allNames;
}, {});
// countedNames :
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 } 

5.按属性对object分类

var people = [{ name: 'Alice', age: 21 },{ name: 'Max', age: 20 },{ name: 'Jane', age: 20 }
];
function groupBy(objectArray, property) {return objectArray.reduce(function (acc, obj) {var key = obj[property];if (!acc[key]) {acc[key] = [];}acc[key].push(obj);return acc;}, {});
}
var groupedPeople = groupBy(people, 'age');
// groupedPeople :
// { 
// 20: [
// { name: 'Max', age: 20 }, 
// { name: 'Jane', age: 20 }
// ], 
// 21: [{ name: 'Alice', age: 21 }] 
// } 

最后

最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。



有需要的小伙伴,可以点击下方卡片领取,无偿分享


版权声明:本文为qq_53225741原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。