js reduce函数详解

js reduce函数详解

💡 原文中文,约2900字,阅读约需7分钟。
📝

内容提要

reduce() 是 JavaScript 数组归并方法,对每个元素执行回调并汇总为单个返回值。语法为 arr.reduce((prev,cur,index,arr)=>{},init),prev 为累计值,cur 为当前元素,init 为初始值。它可替代循环实现数组求和、统计元素出现次数、数组去重、按属性分组、计算一维数组动态和等,能同时将前面遍历结果与当前项运算,这是 forEach、map、filter 等方法不具备的。

🔎

延伸解读

初始值决定遍历起点与安全性

文章指出,若提供 init 初始值,index 从 0 开始;否则从 1 开始,且 prev 首次为数组第一个元素。这意味着不传初始值时,空数组调用 reduce 会报错,而传初始值可避免。示例中求和、计数、去重均显式传入初始值,体现了这一实践。

累计器可复用为多种数据结构

从示例可见,reduce 的累计器不限于数字:求和时是数值,计数时是对象,去重时是数组,分组时也是对象。关键在于每次回调返回的累计器类型与初始值一致,后续逻辑基于该类型操作。这解释了为何 reduce 能替代多种循环模式。

与 forEach/map/filter 的核心差异

文章强调,reduce 与 forEach、map、filter 一样遍历数组,但能同时将前面遍历产生的结果与当前项运算,并汇总为单个返回值。其他迭代方法通常只关注当前项或生成新数组,不直接携带跨项累计状态,因此 reduce 更适合需要聚合的场景。

动态和示例存在副作用与结果疑点

例5 中 runningSum 通过 reduce 直接修改原数组 nums[i],属于副作用写法,且注释输出为 15,但按代码逻辑应得到累计和数组 [1,3,6,10,15]。读者需注意该示例的注释与实现可能不一致,实际使用时应明确是否需要修改原数组。

❓

Q&A

reduce函数的语法和参数具体是什么意思?

reduce() 的语法是 arr.reduce((prev, cur, index, arr) => { ... }, init)。其中 prev 是累计器,表示上一次回调的返回值或初始值 init;cur 是当前正在处理的数组元素;index 是当前元素的索引(可选,若提供 init 则起始索引为 0,否则为 1);arr 是原数组(可选);init 是初始值(可选)。

reduce方法能用来做哪些事情?

reduce 可以替代循环实现多种操作,例如数组求和、数组求积、统计数组中元素出现的次数、数组去重、按属性分组、计算一维数组的动态和等。

reduce和forEach、map、filter有什么区别?

reduce 是数组的归并方法,与 forEach、map、filter 一样都会遍历数组每一项,但 reduce 可以同时将前面遍历产生的结果与当前遍历项进行运算,最终汇总为一个返回值,这是其他迭代方法不具备的。

如何用reduce统计数组中每个元素出现的次数?

可以设置初始值为空对象,在回调中判断当前元素是否已作为属性存在于累计对象中:如果存在则属性值加1,否则将属性值设为1,最后返回累计对象。例如:names.reduce((allNames, name) => { if (name in allNames) { allNames[name]++; } else { allNames[name] = 1; } return allNames; }, {})。

怎样使用reduce实现数组去重?

有两种常见方式:1)设置初始值为空数组,遍历时用 indexOf 检查累计数组中是否已包含当前元素,若没有则 push 进去;2)先对数组排序,然后设置初始值为空数组,遍历时检查累计数组是否为空或最后一个元素是否不等于当前元素,满足则 push。例如:arr.sort().reduce((prev, cur) => { if (prev.length === 0 || prev[prev.length-1] !== cur) { prev.push(cur); } return prev; }, [])。

reduce如何实现按对象属性分组?

可以设置初始值为空对象,在回调中获取当前对象的指定属性值作为 key,检查累计对象中是否已有该 key,没有则赋值为空数组,然后将当前对象 push 到该 key 对应的数组中,最后返回累计对象。例如:function groupBy(objectArray, property) { return objectArray.reduce((prev, cur) => { var key = cur[property]; if (!prev[key]) { prev[key] = []; } prev[key].push(cur); return prev; }, {}); }。

🏷️

标签

➡️

继续阅读