前言
女朋友问我能不能给她讲讲reduce,想想之前对reduce理解的也不是很深刻,这次正好趁着给她讲解的功夫自己也巩固一下。
语法
arr.reduce(callback, [initialValue])
reduce为数组中的每个元素依次执行callback函数,不包括数组中被删除或从未被赋值的元素,callback函数接收四个参数:
- accumulator 累计器
- currentValue 当前值
- currentIndex 当前索引
- array 数组
initialValue
initialValue是可选值,看似不太重要,但是对accumulator和currentValue却有着很重要的影响。
当initialValue不存在时
let arr = [1, 2, 3, 4];
let sum = arr.reduce((acc, cur, index)=>{
console.log(acc, cur, index);
return acc + cur;
});
console.log(sum)
输出结果为:
1 2 1
3 3 2
6 4 3
10
从上述例子可以看出,当initialValue不存在时,当第一次循环时accumulator为数组的第一个元素,currentValue为数组的第二个元素,之后的循环accumulator为前一个循环的return返回值,currentValue为之后的元素,数组总共有4个元素,但是只循环了三次。
当存在initialValue时
let arr = [1, 2, 3, 4];
let sum = arr.reduce((acc, cur, index)=>{
console.log(acc, cur, index);
return acc + cur;
}, 0);
console.log(sum);
输出结果为:
0 1 0
1 2 1
3 3 2
6 4 3
10
上述例子可以看出,当initialValue存在时,在第一次循环时accumulator为initialValue的值,currentValue为数组的第一个值,之后的循环accumulator为前一个循环的return返回值,currentValue为之后的元素,数组总共有4个元素,就执行了4次循环。
当数组为空时
let arr = [];
let sum = arr.reduce((acc, cur, index)=>{
return acc + cur;
})
//报错,"TypeError: Reduce of empty array with no initial value"
let arr = [];
let sum = arr.reduce((acc, cur, index)=>{
return acc + cur;
}, 0)
console.log(sum); // 0
当数组为空时,没有写initialValue参数,会直接报错,所以以防万一,尽量填写initialValue。
reduce的应用
循循环有很多种,为什么要应用reduce?难道是为了提高逼格嘛!!!其实不排除这种可能😂 接下来讲解一些reduce的骚操作:
1、求和
let arr = [1, 2, 3, 4, 5, 6];
let sum = arr.reduce((acc, cur)=>{
return acc + cur;
}, 0)
console.log(sum);
2、二维数组降为一维数组
let arr = [[1, 2], [3, 4], [5, 6]];
let flattened = arr.reduce((acc, cur)=>{
return acc.concat(cur);
}, [])
3、计算数组中每个元素出现的次数
话说这个问题当时面试的时候遇到过,求的是一篇英文文章中,字母出现的次数,其实跟这个差不多,当时写的很复杂,现在想想如果当初选择了这个方法就会好很多。
let names = ['James', 'Bob', 'Alice', 'Bob', 'John'];
let countedNames = names.reduce((acc, cur)=>{
if (cur in acc) {
acc[cur]++;
} else {
acc[cur] = 1;
}
return acc;
}, {})
4、按属性对object分类
let people = [
{name: 'Alice', age: 21},
{name: 'James', age: 20},
{name: 'John', age: 20}
];
const groupBy = (objectArray, property)=>{
return objectArray.reduce((acc, cur)=>{
let key = cur[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(cur);
return acc;
}, {})
};
let gruopedPeople = groupBy(people, ‘age’);
5、数组去重
let arr = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 5];
let result = arr.reduce((acc, cur)=>{
if (!acc.includes(cur)) {
acc.push(cur);
}
return acc;
}, [])
6、redux中的compose函数
官方代码如下:
export default 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)));
}
compose的返回值还是一个函数,调用这个函数所传递的参数将会作为compose最后一个参数的参数,由内向外,逐步调用。 reduce执行过程:
funcs = [f1, f2, f3];
loop1: a = f1, b = f2, ret1 = (...args) => f1(f2(...args))
loop2: a = ret1, b = f3, ret2 = (...args) => ret1(f3(...args)) , 即 ret2 = (...args) => f1(f2(f3(...args)))
后语
觉得还可以的,麻烦走的时候能给点个赞,大家一起学习和探讨!
还可以关注我的博客希望能给我的github上点个Start,小伙伴们一定会发现一个问题,我的所有用户名几乎都与番茄有关,因为我真的很喜欢吃番茄❤️!!!
想跟车不迷路的小伙还希望可以关注公众号 前端老番茄 或者扫一扫下面的二维码👇👇👇。关注后我拉你进前端进阶群,大家一起交流,一起学习,还可以获取免费的资料哦!!!
我是一个编程界的小学生,您的鼓励是我不断前进的动力,😄希望能一起加油前进。
本文使用 mdnice 排版