JavaScript中的数组方法reduce详解
字数 1162 2025-11-05 08:31:58
JavaScript中的数组方法reduce详解
描述:
reduce是JavaScript数组的一个高阶函数,用于将数组元素通过回调函数累积为单个值。它遍历数组,从左到右依次处理每个元素,并保留一个中间结果(累积值)。reduce的核心在于“收敛”逻辑,常用于求和、扁平化、分组等复杂操作。
1. reduce的基本语法
arr.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)
- callback:处理每个元素的函数,包含以下参数:
accumulator:累积值(上一次回调的返回值或初始值)。currentValue:当前处理的数组元素。currentIndex(可选):当前元素的索引。array(可选):原始数组。
- initialValue(可选):初始累积值。若省略,则使用数组第一个元素作为初始值,并从第二个元素开始遍历。
2. 执行步骤详解
假设对数组 [1, 2, 3, 4] 调用 reduce:
情况1:无初始值(initialValue省略)
const result = [1, 2, 3, 4].reduce((acc, cur) => acc + cur);
执行过程:
- 第一次回调:
acc取数组第一个元素1,cur取第二个元素2,返回1 + 2 = 3。 - 第二次回调:
acc = 3,cur = 3,返回3 + 3 = 6。 - 第三次回调:
acc = 6,cur = 4,返回6 + 4 = 10。 - 最终结果:
10。
注意:无初始值时,遍历次数为 数组长度 - 1。
情况2:有初始值(initialValue = 10)
const result = [1, 2, 3, 4].reduce((acc, cur) => acc + cur, 10);
执行过程:
- 第一次回调:
acc = 10,cur = 1,返回10 + 1 = 11。 - 第二次回调:
acc = 11,cur = 2,返回11 + 2 = 13。 - 第三次回调:
acc = 13,cur = 3,返回13 + 3 = 16。 - 第四次回调:
acc = 16,cur = 4,返回16 + 4 = 20。 - 最终结果:
20。
关键区别:有初始值时,遍历次数等于数组长度,且回调从第一个元素开始处理。
3. 常见应用场景
场景1:求和(基础用法)
const sum = [1, 2, 3].reduce((acc, cur) => acc + cur, 0); // 6
场景2:扁平化二维数组
const flattened = [[1, 2], [3, 4]].reduce((acc, cur) => acc.concat(cur), []); // [1, 2, 3, 4]
等价于ES2019的 Array.prototype.flat()。
场景3:统计元素出现次数
const fruits = ['apple', 'banana', 'apple', 'orange'];
const count = fruits.reduce((acc, cur) => {
acc[cur] = (acc[cur] || 0) + 1;
return acc;
}, {}); // { apple: 2, banana: 1, orange: 1 }
场景4:按属性分组
const people = [
{ name: 'Alice', age: 21 },
{ name: 'Bob', age: 21 },
{ name: 'Charlie', age: 22 }
];
const grouped = people.reduce((acc, cur) => {
const key = cur.age;
if (!acc[key]) acc[key] = [];
acc[key].push(cur);
return acc;
}, {});
// 结果:{ 21: [{...}, {...}], 22: [{...}] }
4. 注意事项
-
空数组无初始值会报错:
[].reduce((acc, cur) => acc + cur); // TypeError始终为可能为空的数组指定初始值。
-
累积值类型灵活:可以是数字、数组、对象等,根据需要设计回调逻辑。
-
避免修改原数组:reduce应是无副作用的纯函数操作。
5. 扩展:reduceRight
reduceRight 与 reduce 逻辑相同,但从右向左遍历数组:
const result = [1, 2, 3].reduceRight((acc, cur) => acc - cur, 0); // 0 - 3 - 2 - 1 = -6
通过掌握reduce,可以替代部分循环或递归逻辑,使代码更函数式、简洁。