概述:javaScript中Array中不止reduce方法,还包含foreach,map,filter等等,这里主要介绍是reduce方法。
reduce()从左到右累计数据,直到最后为一个值(也就是最终的结果),听起来还是比较抽象的,累计注意可以是数据,也是字符串编辑
1.语法:
arr.reduce(callback, [initialValue])
参数解析:
arr:表示要累计的数组
callback:回调函数(也就是你要对数组怎么处理)
回调函数中有四个参数:
accumulator:累计结果,最近一次回调产生结果,或者是初始值(如果提供的话)
currentValue:当前值,也就是进行处理的下一个值
currentIndex:表示当前值的索引(从0开始),如果有初始值提供的索引为1
array:需要累计数组
initialValue:初始值(可选参数)如果提供就是第一次回调的第一个参数(accumulator),没有提供就取数组第一个元素,如果既没有提供初始化参数又是个空数组就会抛出异常
2.描述:
如果第一次回调传入初始值,那么accumulator就是初始值,而currentValue就是数组的第一个值,如果没有提供初始值,那么accumulator将会取数组第一个值,currentValue当然是第二个值
如果数组是空,而有没有初始化值,将会抛出TypeError(类型异常),如果数组是空,而传入初始值 或者 没有传入初始值,数组只有一个元素,那个不会调用回调函数,直接返回这个元素的值或者是初始值
//这些是arrow function(箭头函数)
var maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x );
var maxCallback2 = ( max, cur ) => Math.max( max, cur );
// 调用reduce方法没有传入初始值
[ { x: 22 }, { x: 42 } ].reduce( maxCallback ); // 结果为42
[ { x: 22 } ].reduce( maxCallback ); // 结果为:{ x: 22 }
[ ].reduce( maxCallback ); // 抛出异常 TypeError
// 数组map进行遍历的到x对应的数字(预先处理一步),再回调
[ { x: 22 }, { x: 42 } ].map( el => el.x )
.reduce( maxCallback2, -Infinity );
3.reduce()具体的工作过程
[0, 1, 2, 3, 4].reduce(
function (
accumulator,
currentValue,
currentIndex,
array
) { return accumulator + currentValue; });
具体回调请如下表(没有传入初始值)
回调 | 累计值 | 当前值 | 当前索引 | 数组 | 返回值 |
第一次 | 0 | 1 | 1 | [0,1,2,3,4] | 1 |
第二次 | 1 | 2 | 2 | [0,1,2,3,4] | 3 |
第三次 | 3 | 3 | 3 | [0,1,2,3,4] | 6 |
第四次 | 6 | 4 | 4 | [0,1,2,3,4] | 10 |
[0,1,2,3,4].reduce((prev, curr)=> prev + curr );
对于传入初始化值情况
[0, 1, 2, 3, 4].reduce(
(accumulator, currentValue, currentIndex, array) => {
return accumulator + currentValue;
},
10
);
传入初始值为10,返回20
回调 | 累计值 | 当前值 | 当前索引 | 数组 | 返回值 |
第一次 | 10 | 0 | 0 | [0,1,2,3,4] | 10 |
第二次 | 10 | 1 | 1 | [0,1,2,3,4] | 11 |
第三次 | 11 | 2 | 2 | [0,1,2,3,4] | 13 |
第四次 | 13 | 3 | 3 | [0,1,2,3,4] | 16 |
第五次 | 16 | 4 | 4 | [0,1,2,3,4] | 20 |
4.例子走起
var sum = [0, 1, 2, 3].reduce(function (a, b) {
return a + b;
}, 0);
// sum is 6
可以用箭头函数
var total = [ 0, 1, 2, 3 ].reduce(
( acc, cur ) => acc + cur,
0
);
b.拼接字符串
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
function(a, b) {
return a.concat(b);
},
[]
);
// 拼接的结果为 [0, 1, 2, 3, 4, 5]
可用箭头函数
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
( acc, cur ) => acc.concat(cur),
[]
);
c.字段计数
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function (allNames, name) {
if (name in allNames) {
//对应name字段累计1
allNames[name]++;
}
else {
//新建一个name字段数字为1
allNames[name] = 1;
}
return allNames;
}, {});
console.log(countedNames);
// countedNames 的结果为:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
d.继续扩展
// friends -y一个数组对象
// 对象中字段books表示所有喜欢的书
var friends = [{
name: 'Anna',
books: ['Bible', 'Harry Potter'],
age: 21
}, {
name: 'Bob',
books: ['War and peace', 'Romeo and Juliet'],
age: 26
}, {
name: 'Alice',
books: ['The Lord of the Rings', 'The Shining'],
age: 18
}];
// 列出所有朋友喜欢的书+初始值的书
var allbooks = friends.reduce(function(prev, curr) {
//称为rest 参数,详情参考https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
return [...prev, ...curr.books];
}, ['Alphabet']);
//结果为:
// allbooks = [
// 'Alphabet', 'Bible', 'Harry Potter', 'War and peace',
// 'Romeo and Juliet', 'The Lord of the Rings',
// 'The Shining'
// ]
5.浏览器兼容情况 最低版本
Chrome 支持, firefox 3.0(1.9),IE 9 , Opera 10.5 , Safari 4.0
总结:
reduce()功能还是很强大的,主要累计操作,累加或拼接等等,只要是积累操作都可以考虑用reduce。
本文参考官方文档:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce?v=control