JS使用reduce按日期聚合交易数据时不同MaterialID返回值一致问题
问题根因
你的问题核心是JavaScript引用类型的共享引用问题。你预先定义的dateObj是对象类型,属于引用值,你在初始化每个物料的monthlyVolume字段时直接将dateObj赋值过去,本质上所有物料的monthlyVolume都指向内存中同一个dateObj实例,任意物料修改月度统计的sum或count,都会直接修改全局的dateObj,最终所有物料的统计数据会完全同步。
解决方法
每次初始化新物料的月度统计数据时,创建一份全新的初始统计对象,避免所有物料共享同一个dateObj引用。
修正后代码
你可以单独封装一个获取初始月度统计对象的方法,每次初始化新物料时调用该方法拿到独立的统计对象:
// 每次调用返回独立的初始月度统计对象 const getInitMonthlyVolume = () => ({ "Jan-20": { sum: 0, count: 0 }, "Feb-20": { sum: 0, count: 0 }, "Mar-20": { sum: 0, count: 0 }, "Apr-20": { sum: 0, count: 0 } }) let result = transactionData.reduce((acc, { MaterialID, TransactionDate, TransactionQuantity }) => { const date = dayjs(TransactionDate).format("MMM-YY"); // 初始化物料时使用全新的统计对象 const _material = acc[MaterialID] ??= { monthlyVolume: getInitMonthlyVolume() }; _material.monthlyVolume[date].sum += parseFloat(TransactionQuantity); _material.monthlyVolume[date].count++; return acc; }, {})
如果不想单独封装方法,也可以对原始dateObj做深拷贝实现相同效果:
let result = transactionData.reduce((acc, { MaterialID, TransactionDate, TransactionQuantity }) => { const date = dayjs(TransactionDate).format("MMM-YY"); // 用JSON序列化的方式深拷贝dateObj,得到独立的初始统计对象 const _material = acc[MaterialID] ??= { monthlyVolume: JSON.parse(JSON.stringify(dateObj)) }; _material.monthlyVolume[date].sum += parseFloat(TransactionQuantity); _material.monthlyVolume[date].count++; return acc; }, {})
内容的提问来源于stack exchange,提问作者TW3
相关产品推荐
相关产品推荐

