「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战」
引子
reduce方法非常灵活,对初学者而言,数组的reduce方法并没有那么容易理解,reduce能完成的事情for或者foreach也能完成,但是弄懂reduce方法之后,在别人的代码中遇见reduce,不至于有挫败的感觉。 大部分的数组方法,都返回一个新的数组,而reduce方法返回的值,却它可以返回任意类型的值,可以是数字、字符串,甚至可以是对象或新数组。从这里就能看出来它有多灵活。
简单理解
reduce方法会对数组元素逐一的执行回调函数,然后返回一个累积的值,用生活中的例子就是,做菜,购买了各种食材后,数组里的元素,就是油、盐、味精、青菜、香菇,最后把他们做成一道青菜香菇, 对他们分别的处理就是reducer函数。
语法:
arr.reduce(callback,[initialValue])
-
callback (执行数组中每个值的函数,包含四个参数)
- previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
- currentValue (数组中当前被处理的元素)
- index (当前元素在数组中的索引)
- array (调用 reduce 的数组)
-
initialValue (作为第一次调用 callback 的第一个参数。)
initialValue
当initialValue不存在时
当initialValue不存在时,当第一次循环时previousValue为数组的第一个元素,currentValue为数组的第二个元素,之后的循环previousValue为前一个循环的return返回值,currentValue为之后的元素,假设数组总共有n个元素,只会循环n+1次。
当存在initialValue时
当initialValue存在时,在第一次循环时previousValue为initialValue的值,currentValue为数组的第一个值,之后的循环previousValue为前一个循环的return返回值,currentValue为之后的元素,假设数组总共有n个元素,将会执行了n次循环。
reduce的应用
求和求积
function Accumulation(...vals) {
return vals.reduce((t, v) => t + v, 0);
}
function Multiplication(...vals) {
return vals.reduce((t, v) => t * v, 1);
}
Accumulation(1, 2, 3, 4, 5); // 15
Multiplication(1, 2, 3, 4, 5); // 120
权重求和
const scores = [
{ score: 90, subject: "chinese", weight: 0.5 },
{ score: 95, subject: "math", weight: 0.3 },
{ score: 85, subject: "english", weight: 0.2 }
];
const result = scores.reduce((t, v) => t + v.score * v.weight, 0); // 90.5
代替reverse
function Reverse(arr = []) {
return arr.reduceRight((t, v) => (t.push(v), t), []);
}
Reverse([1, 2, 3, 4, 5]); // [5, 4, 3, 2, 1]
按属性对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’);
复制代码
代替map和filter
const arr = [0, 1, 2, 3];
// 代替map:[0, 2, 4, 6]
const a = arr.map(v => v * 2);
const b = arr.reduce((t, v) => [...t, v * 2], []);
// 代替filter:[2, 3]
const c = arr.filter(v => v > 1);
const d = arr.reduce((t, v) => v > 1 ? [...t, v] : t, []);
// 代替map和filter:[4, 6]
const e = arr.map(v => v * 2).filter(v => v > 2);
const f = arr.reduce((t, v) => v * 2 > 2 ? [...t, v * 2] : t, []);
数组降维
function Flat(arr = []) {
return arr.reduce((t, v) => t.concat(Array.isArray(v) ? Flat(v) : v), [])
}
const arr = [0, 1, [2, 3], [4, 5, [6, 7]], [8, [9, 10, [11, 12]]]];
Flat(arr); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
总结
虽然reduce方法能完成的工作for或者foreach也能完成,但是高级函数reduce语义性更强,reduce函数理解的难度比其他数组方法稍微难点,但是稍微花点时间去学习,带来的收益还是挺高的。