为何JavaScript在部分场景下会残留一个空数组?
问题:forEach遍历删除空数组时残留空元素的原因及解决办法
我需要处理大量已排序数组,通过三层循环筛选数据后生成了包含空数组的chartTypeData,尝试用以下代码删除空数组,但部分场景下总会残留一个空数组:
chartTypeData.forEach((item: any, index: any) => { if (item.length === 0) { chartTypeData.splice(index, 1); } });
完整代码:
for (let i = 0; i < chartType.length; i++) { const chartItem = chartsData?.product?.data[0].attributes.product_charts.data; for (let j = 0; j < chartCategory.length; j++) { for (let k = 0; k < country.length; k++) { chartTypeData.push( chartItem.filter((item: any) => { return ( item.attributes.type === chartType[i] && item.attributes.chartCategory === chartCategory[j] && item.attributes.country === country[k] ); }) ); } chartTypeData[i].sort((a: any, b: any) => { return new Date(a.attributes.date).getTime() - new Date(b.attributes.date).getTime(); }); } } chartTypeData.forEach((item: any, index: any) => { if (item.length === 0) { chartTypeData.splice(index, 1); } });
问题原因
核心问题是forEach遍历的同时用splice修改原数组:
forEach是基于数组初始的长度和索引序列进行遍历的。当你删除某个索引的元素后,数组后面的元素会自动往前移位填补空缺,但forEach的遍历索引不会随之调整,会直接跳到下一个初始索引,导致跳过了移位后处于当前索引位置的元素。
举个例子:假设数组是[ [], [], [] ]
- 遍历索引0,删除该元素,数组变成
[ [], [] ] - forEach接下来会遍历索引1,但此时原索引1的元素已经移到了索引0的位置,当前索引1的元素是原索引2的元素
- 这样就漏掉了现在处于索引0的空数组,最终残留一个空元素
解决方法
方案1:用filter创建新数组(最推荐)
直接用filter生成一个不包含空数组的新数组,逻辑简单清晰,且不会修改原数组:
chartTypeData = chartTypeData.filter(item => item.length > 0);
方案2:倒序遍历修改原数组
如果必须修改原数组,倒序遍历可以避免元素移位导致的跳过问题——删除后面的元素不会影响前面还没遍历到的元素索引:
for (let i = chartTypeData.length - 1; i >= 0; i--) { if (chartTypeData[i].length === 0) { chartTypeData.splice(i, 1); } }
方案3:手动调整索引(不推荐,繁琐易出错)
如果坚持要用forEach,可以通过记录偏移量来修正索引,但这种写法不够直观,不如前两种方案:
let offset = 0; chartTypeData.forEach((item, index) => { if (item.length === 0) { chartTypeData.splice(index - offset, 1); offset++; } });
内容的提问来源于stack exchange,提问作者Navro
相关产品推荐
相关产品推荐

