JavaScrip 中 reduce 函数用法详解
在 JavaScript 中,reduce()
是数组对象的一个高阶函数,它用于将数组元素通过指定的规则「累积」为单个值。这个方法的强大之处在于可以灵活处理各种累积需求,如求和、求积、数据转换等。下面我会用通俗易懂的方式为你详细解释。
1️⃣ 基本语法
javascript
复制
下载
arr.reduce(callback(accumulator, currentValue, index, array), initialValue)
-
callback
:处理每个元素的回调函数 -
accumulator
:累积器(累积的结果) -
currentValue
:当前处理的数组元素 -
index
(可选):当前元素的索引 -
array
(可选):调用 reduce 的数组 -
initialValue
(可选):初始累积值(如果省略,默认用数组第一个元素)
2️⃣ 核心作用
将数组中的每个元素依次执行回调函数,并将结果「累积」起来,最终得到一个值。
3️⃣ 基础示例:数组求和
javascript
复制
下载
const nums = [1, 2, 3, 4]; const sum = nums.reduce((acc, current) => acc + current, 0); console.log(sum); // 10
-
执行过程:
-
初始累积值
acc = 0
(由initialValue
指定) -
第一次:
acc = 0 + 1 = 1
-
第二次:
acc = 1 + 2 = 3
-
第三次:
acc = 3 + 3 = 6
-
第四次:
acc = 6 + 4 = 10
-
4️⃣ 不提供初始值的情况
如果省略 initialValue
,默认用数组第一个元素作为初始值:
javascript
复制
下载
const nums = [1, 2, 3, 4]; const sum = nums.reduce((acc, current) => acc + current); // 相当于:初始值 acc = 1,然后依次加 2, 3, 4 console.log(sum); // 10
⚠️ 注意:空数组调用 reduce
且不提供初始值时会报错!
5️⃣ 复杂示例:对象数组的累积
计算购物车中商品总价:
javascript
复制
下载
const cart = [{ name: "苹果", price: 10, count: 2 },{ name: "香蕉", price: 5, count: 3 },{ name: "橘子", price: 8, count: 1 } ];const total = cart.reduce((acc, item) => {return acc + (item.price * item.count); }, 0);console.log(total); // 10*2 + 5*3 + 8*1 = 43
6️⃣ 进阶用法
🔹 将二维数组扁平化
javascript
复制
下载
const arr2D = [[1, 2], [3, 4], [5, 6]]; const flat = arr2D.reduce((acc, current) => acc.concat(current), []); console.log(flat); // [1, 2, 3, 4, 5, 6]
🔹 统计元素出现次数
javascript
复制
下载
const fruits = ['苹果', '香蕉', '苹果', '橘子', '香蕉']; const count = fruits.reduce((acc, fruit) => {acc[fruit] = (acc[fruit] || 0) + 1;return acc; }, {});console.log(count); // { 苹果:2, 香蕉:2, 橘子:1 }
7️⃣ 常见错误
❌ 忘记返回累积值
javascript
复制
下载
// 错误示例:没有返回 acc const sum = nums.reduce((acc, num) => {acc + num; // ❌ 没有 return }, 0); // 结果:sum = 0(因为每次返回 undefined,最后累积器保持初始值)
❌ 对空数组不使用初始值
javascript
复制
下载
[].reduce((acc, num) => acc + num); // ❌ 报错!
8️⃣ 总结
-
何时使用 reduce:需要将数组元素按规则合并为一个值时。
-
关键点:
-
回调函数必须返回新的累积值。
-
处理对象或复杂操作时,提供初始值更安全。
-
-
优势:代码简洁,适合链式操作。
使用 for 累计金额:
let total = 0;
for (let i = 0; i < ckd.ckDetailList.length; i++) {const item = ckd.ckDetailList[i];// 累计金额total += item.total;
}
使用 forEach 累计金额:
let total = 0;
ckd.ckDetailList.forEach((item) => {item.total = Number(formatToRMB(item.total));// 累计金额total += item.total;
});
使用 reduce 累计金额:
let total = Number(ckDetail.value.reduce((pre, cur) => pre + cur.total, 0).toFixed(2));