reduce()方法将一个累加器和一个阵列元素从左至右依次传入一个回调函数,并最终返回一个值.
最终返回的值由回调函数的规则来决定.
一\语法
arr.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)
注释说明:
-
callback: 用于处理阵列中每个元素的函数,可以传入四个参数
- accumulator:累加器.用来累积回调函数的累加器,对于累加器的初始值,如果有设定,即设定有初值,那么这个累加器在第一次执行回调函数时就是这个初始值 (initialValue),如果没有设定初始值,那么第一次执行回调函数时,累加器就等于陈列元素的第0项值.之后每次调用回调函数时,累加器的值就等于上次执行函数的结果.
- currentvalue:当前值.当前值是指每次执行回调函数时从左到右的依次值.如果设定了累加器的初始值,那么执行回调函数时就从陈列元素的第0项开始做为当前值,依次向右;如果没有设定初始值 ,那么陈列元素的第0项将作为累加器的值,第一项则成了第一次回调时的当前值..
- currentIndex:当前索引.原陣列当前所迭代處理中的元素之索引。若有傳入
initialValue,則由索引 0 之元素開始,若無則自索引 1 之元素開始。为可选参数 - array:数组.呼叫
reduce()方法的陣列,是个可选参数,可以不指定,即默认为arr.
所以,本方法实际必需要传入的参数仅有两个,即accumulator(累加器)和当前值(currentValue).所以本方法的最简化语法就是:
arr.reduce(callback[accumulator,currentValue])二\请注意
- 如果陈列元素为空,且没有提供初始值(initalValue),该方法将为抛出类型错误(TypeError)
- 如果陈列元素只有一个值 ,且没有提供初始值,或虽然提供了初始值但阵列为空,那就将这个唯一的值回传而不调用回调函数
三\reduce()的工作方法
1\将阵列中的所有元素值相加
例1:无初始值的累加
let arr = [1,2,3,4];
let arr2 = arr.reduce((a,b)=>a+b);
console.log(arr2);
//10
//当然上方代码中的箭头函数也可以写function函数,其执行结果一样.即:
let arr2 = arr.reduce(function(a,b){
return a+b;
});
//以上示例是没有指定初始值的情况,其执行过程如下表所示:
| callback | accumulator | currentValue | currentIndex | arr | return value |
|---|---|---|---|---|---|
| 第一次 | 1 | 2 | 1 | [1,2,3,4] | 3 |
| 第二次 | 3 | 3 | 2 | [1,2,3,4] | 6 |
| 第三次 | 6 | 4 | 3 | [1,2,3,4] | 10 |
例2:有初始值 的累加
let arr = [1,2,3,4];
let arr2 = arr.reduce((a,b)=>{return a+b},10);
console.log(arr2);
//20
//或者写成:
let arr2 = arr.reduce(function(a,b){
return a+b;
},10);
//本例代码是指定的初始值的情况,其执行过程如下:
| callback | accumulator | currentValue | currentIndex | arr | return Value |
|---|---|---|---|---|---|
| 第一次 | 10 | 1 | 0 | [1,2,3,4] | 11 |
| 第二次 | 11 | 2 | 1 | [1,2,3,4] | 13 |
| 第三次 | 13 | 3 | 2 | [1,2,3,4] | 16 |
| 第四次 | 16 | 4 | 3 | [1,2,3,4] | 20 |
2\摊平一个多维阵列
可以借助数组的concat()方法,使用reduce()方法将一个多维数组摊平.
例:
let arr = [[1,2],[3,4],[5,6],[7,8]];
let arr2 = arr.reduce(function(a,b){
return a.concat(b);
},[]);
console.log(arr2) //[1,2,3,4,5,6,7,8]
//或者使用箭头函数,写成:
let arr2 = arr.reduce((a,b)=>a.concat(b));
console.log(arr2) //[1,2,3,4,5,6,7,8] 执行结果一样
3/计算相同元素数量并以键值对表示
可以使用reduce()方法来遍历一个数组,并找出数组中的相同项,例:
let names = ["Alice","张加成","李大营","Bob","John","张加成"];
let countedNames = names.reduce(function(allNames,name){
if(name in allNames){
allNames[name]++;
}else{
allNames[name] = 1;
}
return allNames;
},{});
console.log(countedNames);
//{Alice: 1, 张加成: 2, 李大营: 1, Bob: 1, John: 1};
//在本例中,先初始化一个空对像作为累加器,然后使用reduce()方法遍历数组names,将数组中的每个一名字与累加器对像中的名字做对比,如果原累加器中没有遍历到的名字,则将该名字写入累加器,并将其值设置为1;如果累加器中已经存在该名字,那么它的值就自动加1;其执行过程如下:
| callback | accumulator | currentValue | currentIndex | return value |
|---|---|---|---|---|
| 第一次 | {} | "Alice" | 0 | {Alice:1} |
| 第二次 | {Alice:1} | "张加成" | 1 | {Alice:1,张加成:1} |
| 第三次 | {Alice:1,张加成:1} | "李大营" | 2 | {Alice:1,张加成:1,李大营:1} |
| 第四次 | {Alice:1,张加成:1,李大营:1} | "Bob" | 3 | {Alice:1,张加成:1,李大营:1,Bob:1} |
| 第五次 | {Alice:1,张加成:1,李大营:1,Bob:1} | "John" | 4 | {Alice:1,张加成:1,李大营:1,Bob:1,John:1} |
| 第六次 | {Alice:1,张加成:1,李大营:1,Bob:1,John:1} | "张加成" | 5 | {Alice:1,张加成:2,李大营:1,Bob:1,John:1} |
最终返回值为:{Alice:1, 张加成:2, 李大营:1, Bob:1,John:1 }
4\使用展开运算符和给定的初始值,结合数组中的阵列元素
例:
let friends = [{
name:"赵小亮",
books:["《罗密欧与朱丽叶》","《简爱》","《奋斗》"],
age:28
},{
name:"张二牛",
books:["《HTML&CSS》","《javascript程序开发》","《JAVAscript权威指南》"],
age:21
},{
name:"李新书",
books:["《平凡的世界》","《和你在一起》","《天道》"],
age:32
},{
name:"王五四",
books:["《红高梁》","《平凡的世界》","《民俗通书》"],
age:41
}
];
let allBooks = friends.reduce(function(prev,curr){
return [...prev,...curr.books]
},["《王二小放牛》"])
console.log(allBooks);
// 在本例中,先将一个数组["《王二小放牛》"]作为初始值,然后,使用数组的reduce()方法对目标数组friends中的每一项进行遍历,并使用展开运算符“...”将初始值和遍历后所得到的books的值(也是个数组)展开后重新放入初始数组中返回出来。
5、结合排序的方法将数组中重复的序号去除
例:
let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4,];
let result = arr.sort().reduce((init,current)=>{
if(init.length === 0 || init[init.lenght-1]!==current){
init.push(current);
}
return init;
},[])
console.log(result);
//[1, 2, 3, 4, 5]
//本例中,先对原数组进行从小到大的排序,然后使用reduce()方法对排序后的数组进行遍历,先初始化一个累加器为一个空数组。然后在遍历的过程中,判断累加器数组的长度,如果数组长度为0,即空数组,或者,数组中第(数组长度减1)的位置的值不等于当前值,那就当前值添加到数组中(反之就不添加)。这样就把排序后的数组中重复的数字给筛选了来了。
6、序列执行promise
例:
function runPromiseInSequense(arr) {
return arr.reduce((promiseChain, currentPromise) => {
return promiseChain.then((chainedResult) => {
return currentPromise(chainedResult)
.then((res) => res)
})
}, Promise.resolve());
}
// promise function 1
function p1() {
return new Promise((resolve, reject) => {
resolve(5);
});
}
// promise function 2
function p2(a) {
return new Promise((resolve, reject) => {
resolve(a * 2);
});
}
// promise function 3
function p3(a) {
return new Promise((resolve, reject) => {
resolve(a * 3);
});
}
const promiseArr = [p1, p2, p3];
runPromiseInSequense(promiseArr)
.then((res) => {
console.log(res); // 30
});