JavaScript数组通过reduce转换为统计对象的分步原理解析
数组元素统计:reduce方法的运行机制与分步流程
先看你给出的代码:
const arr = [1, 3, 1, 2, 5, 2, 3, 4, 1, 2, 3, 4, 3] const resultado = arr.reduce((prev, cur) => ((prev[cur] = prev[cur] + 1 || 1), prev), {}) // resultado = { 1: 3, 2: 3, 3: 4, 4: 2, 5: 1 }
一、核心逻辑:用reduce实现元素计数
Array.reduce()是JS中用来遍历数组并累计结果的方法,这里的作用是把数组转换成统计元素出现次数的对象,核心参数有两个:
- 回调函数:每次遍历数组元素时执行,接收两个关键参数:
prev:累计器,存储每次遍历后的中间结果(这里是统计对象)cur:当前正在遍历的数组元素
- 初始值
{}:第一次遍历前,prev的初始值是空对象。
拆解回调函数的写法
回调里的((prev[cur] = prev[cur] + 1 || 1), prev)用了两个JS语法技巧:
- 逗号运算符:逗号分隔的多个表达式会依次执行,最终返回最后一个表达式的值。这里每次执行完计数逻辑后,返回
prev,保证累计器始终是同一个统计对象。 - 逻辑或
||:处理元素第一次出现的情况:- 如果
prev[cur]已经存在(之前统计过),就执行prev[cur] + 1,更新计数 - 如果
prev[cur]不存在(第一次遇到),prev[cur]是undefined,undefined + 1得到NaN,NaN是假值,所以会取||后面的1,完成第一次计数赋值。
- 如果
二、分步遍历流程
跟着数组的每一个元素,一步步看prev的变化:
初始状态:prev = {}
- 遍历第一个元素
1:prev[1]不存在,执行prev[1] = 1→prev = {1: 1} - 遍历第二个元素
3:prev[3]不存在,执行prev[3] = 1→prev = {1: 1, 3: 1} - 遍历第三个元素
1:prev[1]是1,执行1 + 1 = 2→prev = {1: 2, 3: 1} - 遍历第四个元素
2:prev[2]不存在,执行prev[2] = 1→prev = {1: 2, 3: 1, 2: 1} - 遍历第五个元素
5:prev[5]不存在,执行prev[5] = 1→prev = {1: 2, 3: 1, 2: 1, 5: 1} - 遍历第六个元素
2:prev[2]是1,执行1 + 1 = 2→prev = {1: 2, 3: 1, 2: 2, 5: 1} - 遍历第七个元素
3:prev[3]是1,执行1 + 1 = 2→prev = {1: 2, 3: 2, 2: 2, 5: 1} - 遍历第八个元素
4:prev[4]不存在,执行prev[4] = 1→prev = {1: 2, 3: 2, 2: 2, 5: 1, 4: 1} - 遍历第九个元素
1:prev[1]是2,执行2 + 1 = 3→prev = {1: 3, 3: 2, 2: 2, 5: 1, 4: 1} - 遍历第十个元素
2:prev[2]是2,执行2 + 1 = 3→prev = {1: 3, 3: 2, 2: 3, 5: 1, 4: 1} - 遍历第十一个元素
3:prev[3]是2,执行2 + 1 = 3→prev = {1: 3, 3: 3, 2: 3, 5: 1, 4: 1} - 遍历第十二个元素
4:prev[4]是1,执行1 + 1 = 2→prev = {1: 3, 3: 3, 2: 3, 5: 1, 4: 2} - 遍历第十三个元素
3:prev[3]是3,执行3 + 1 = 4→prev = {1: 3, 2: 3, 3: 4, 4: 2, 5: 1}
遍历结束后,prev就是最终的统计结果,赋值给resultado。
内容的提问来源于stack exchange,提问作者Brian Cabrera
相关产品推荐
相关产品推荐

