JavaScript按时间戳分类数组元素,如何优化大数据量下的处理效率?
性能优化方案
原有代码的性能瓶颈
- 重复计算公共参数:每次循环都重新获取当前时间、计算当前年月,完全可以提到循环外只执行1次
- 字符串操作开销过大:使用
toLocaleString()转本地化字符串后再切割提取年月,这个操作的性能远低于直接调用Date对象的原生方法获取数值类型的年月 - 循环存在额外开销:forEach遍历存在函数调用开销,海量数据下普通for循环性能更优
- 额外的逻辑bug:季度判断存在逻辑漏洞,若当前是1、2月,
currentmonth - 3为负数,会将去年年末的错误数据归类到本季度数组
优化实现代码
const thisMonthArray = [] const thisQuarterArray = [] const thisYearArray = [] const data = [ {id:'1',createdOn:1631166889,items:[{itemname:'name1',details:'details1'}]}, {id:'2',createdOn:1625291689,items:[{itemname:'name2',details:'details2'}]}, {id:'3',createdOn:1612335289,items:[{itemname:'name3',details:'details3'}]} ] // 公共参数只计算1次 const now = new Date() const currentYear = now.getFullYear() const currentMonth = now.getMonth() + 1 // getMonth返回0-11,+1转为1-12的自然月 // 自然季度起始月份,若需求为最近3个月可自行调整判断逻辑 const currentQuarterStart = Math.floor((currentMonth - 1) / 3) * 3 + 1 // 改用普通for循环减少函数调用开销 const dataLen = data.length for (let i = 0; i < dataLen; i++) { const element = data[i] const createDate = new Date(element.createdOn * 1000) const createYear = createDate.getFullYear() const createMonth = createDate.getMonth() + 1 if (createYear !== currentYear) continue if (createMonth === currentMonth) { thisMonthArray.push(element) } else if (createMonth >= currentQuarterStart) { thisQuarterArray.push(element) } else { thisYearArray.push(element) } } const results = { createdOn: Date.now(), thisMonth: thisMonthArray, thisQuarter: thisQuarterArray, thisYear: thisYearArray } console.log(results)
额外性能优化提示
如果你的需求是「最近3个月」而非自然季度,可以直接用时间戳数值比较,性能还能再提升30%左右:
// 提前计算3个月前的秒级时间戳,和createdOn单位统一 const threeMonthAgoStamp = Math.floor((new Date(currentYear, currentMonth - 4, 1)).getTime() / 1000) // 循环内无需解析日期年月,直接比较数值即可 if (element.createdOn >= threeMonthAgoStamp) { // 对应归类逻辑 }
内容的提问来源于stack exchange,提问作者Odeh Abuzaid
相关产品推荐
相关产品推荐

