JavaScript如何遍历对象数组统计生成按服务分类的状态计数嵌套对象
问题核心原因
- 你初始化时所有服务共用了同一个
nestedObj对象:JS中对象是引用类型,你把同一个对象赋值给所有服务的属性,后续修改任意一个服务的计数,所有服务的计数都会同步变化,这就是你看到所有计数都等于全局总和的根源 - 初始化逻辑冗余,统计阶段的双层for循环完全没必要,遍历一次数组就可以完成初始化+统计,效率更高
- 统计代码存在语法错误:
countsObj[status = countsObj[status] + 1缺少右方括号,正确写法是countsObj[status] = countsObj[status] + 1
正确实现代码
// 注意原数据里的服务名、状态值需要加引号,否则会被识别为变量报错 const dataArr = [ {service: 's1', status: 'ready'}, {service: 's2', status: 'ready'}, {service: 's1', status: 'retired'}, {service: 's3', status: 'retired'}, {service: 's2', status: 'ready'} ]; const statusByServiceObj = {}; dataArr.forEach(ele => { // 当前服务未初始化时,新建独立的计数对象,初始值为0 if (!statusByServiceObj[ele.service]) { statusByServiceObj[ele.service] = { ready: 0, retired: 0 }; } // 对应状态计数加1 statusByServiceObj[ele.service][ele.status]++; });
运行后statusByServiceObj输出结果完全符合需求:
{ s1: { ready: 1, retired: 1 }, s2: { ready: 2, retired: 0 }, s3: { ready: 0, retired: 1 } }
相关最佳实践
- 注意引用类型的引用共享问题:不要复用同一个对象/数组赋值给多个属性,每次需要独立值的时候要新建对象,避免多个属性指向同一块内存地址
- 优先用单次遍历完成聚合统计:不需要分开做初始化、统计两次遍历,也不需要嵌套循环遍历已有属性,直接在单次遍历中判断是否存在对应键即可,时间复杂度只有O(n),效率更高
- 数组聚合统计场景可以用
Array.reduce写出更简洁的代码,示例:
const statusByServiceObj = dataArr.reduce((acc, curr) => { if (!acc[curr.service]) { acc[curr.service] = { ready: 0, retired: 0 }; } acc[curr.service][curr.status]++; return acc; }, {});
内容的提问来源于stack exchange,提问作者Kalia Hayes
相关产品推荐
相关产品推荐

