You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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的遍历索引不会随之调整,会直接跳到下一个初始索引,导致跳过了移位后处于当前索引位置的元素。

举个例子:假设数组是[ [], [], [] ]

  1. 遍历索引0,删除该元素,数组变成[ [], [] ]
  2. forEach接下来会遍历索引1,但此时原索引1的元素已经移到了索引0的位置,当前索引1的元素是原索引2的元素
  3. 这样就漏掉了现在处于索引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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 16:05:22