一、一句话定义
reduce = 数组的「压缩器」
它能够将数组中的元素逐个处理,最终「压缩」成一个值(可以是数字、字符串、对象、数组等)
二、基础语法
array.reduce(
(accumulator, currentValue, index, array) => {
// 处理逻辑
return updatedAccumulator;
},
initialValue // 初始值(可选)
);
参数详解
| 参数名 | 作用描述 | 是否可选 |
|---|---|---|
accumulator | 累积值(上一次回调的返回值) | 必选 |
currentValue | 当前处理的数组元素 | 必选 |
index | 当前元素的索引 | 可选 |
array | 原始数组 | 可选 |
initialValue | 初始累积值(不传则默认用第一项) | 可选 |
三、示例
1. 计算总和(购物车结算)
const cart = [
{ product: "Phone", price: 800, amount: 1 },
{ product: "Laptop", price: 1200, amount: 1 },
{ product: "Headphones", price: 100, amount: 2 }
];
const total = cart.reduce((sum, item) =>
sum + item.price * item.amount,
0 // 初始值
);
console.log(`Total: $${total}`); // Total: $2200
2. 数据格式转换(数组 → 对象)
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
];
const userMap = users.reduce((map, user) => {
map[user.id] = user.name;
return map;
}, {});
console.log(userMap);
// { 1: "Alice", 2: "Bob" }
3. 复杂数据聚合(分组统计)
const orders = [
{ product: "Phone", category: "Electronics" },
{ product: "Shirt", category: "Clothing" },
{ product: "Laptop", category: "Electronics" }
];
const categoryCount = orders.reduce((count, order) => {
count[order.category] = (count[order.category] || 0) + 1;
return count;
}, {});
console.log(categoryCount);
// { Electronics: 2, Clothing: 1 }
四、与 map 的对比分析
| 特性 | reduce | map |
|---|---|---|
| 输出类型 | 任意类型(灵活) | 新数组(固定) |
| 状态管理 | 支持累积值(accumulator) | 每次迭代独立 |
| 适用场景 | 聚合、分组、复杂转换 | 一对一元素映射 |
| 性能 | 单次遍历完成复杂操作 | 需要额外操作处理复杂逻辑 |
五、使用技巧与最佳实践
1. 初始值的重要性
// 无初始值(默认用第一项)
[1, 2, 3].reduce((sum, num) => sum + num); // 6
// 有初始值
[].reduce((sum, num) => sum + num, 0); // 0(安全)
2. 链式操作优化
// 传统方式(多次遍历)
const total = cart
.map(item => item.price * item.amount)
.reduce((sum, price) => sum + price, 0);
// 优化版(单次遍历)
const total = cart.reduce((sum, item) =>
sum + item.price * item.amount, 0);
3. 处理异步操作
const fetchData = async (urls) => {
return urls.reduce(async (promise, url) => {
const results = await promise;
const data = await fetch(url).then(res => res.json());
return [...results, data];
}, Promise.resolve([]));
};
六、总结与建议
-
适用场景:数据聚合、复杂转换、状态累积
-
性能优势:单次遍历完成复杂操作
-
学习曲线:比
map/filter稍复杂,但功能更强大 -
建议:
- 始终提供初始值以避免意外错误
- 避免过度嵌套,保持回调函数简洁
- 在需要状态累积时优先选择
reduce