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

删除数组中非数字元素的代码异常:调换元素位置结果不同的原因

数组删除非数字元素时的遍历异常解析

问题场景

尝试编写代码删除数组中的非数字元素,第一段代码执行后输出不符合预期,仍存在非数字元素:

let arr = [1, "5", 3, 27, undefined, { name: 'Steven' }, 11];

for (let i = 0; i < arr.length; i++) {
    if (typeof arr[i] !== 'number') {
        arr.splice(i, 1);
    }
}
console.log(arr); // 输出: [1, 3, 27, {…}, 11]

调换数组中对象与最后一个数字的位置后,输出结果正常:

let arr = [1, "5", 3, 27, undefined, 11, { name: 'Steven' }];

for (let i = 0; i < arr.length; i++) {
    if (typeof arr[i] !== 'number') {
        arr.splice(i, 1);
    }
}
console.log(arr); // 输出: [1, 3, 27, 11]

原因解析

核心问题在于正序遍历数组时使用splice删除元素,会导致数组长度缩短、后续元素索引前移,而循环的i仍在递增,直接跳过了被前移的元素。

第一个例子的执行细节

  1. 初始数组:[1, "5", 3, 27, undefined, { name: 'Steven' }, 11]
  2. i=1时,元素"5"是非数字,执行splice(1,1),数组变为[1, 3, 27, undefined, { name: 'Steven' }, 11],随后i自增到2
  3. i=3时,元素undefined是非数字,执行splice(3,1),数组变为[1, 3, 27, { name: 'Steven' }, 11],i自增到4
  4. 此时i=4对应的元素是11(数字),循环继续直到i等于数组长度(5),循环结束。原本在undefined后的对象被移到了索引3的位置,但i已经跳到4,完全跳过了对这个对象的检查,所以它留在了数组里。

第二个例子的执行细节

  1. 初始数组:[1, "5", 3, 27, undefined, 11, { name: 'Steven' }]
  2. 前面步骤类似,删除"5"和undefined后,数组变为[1, 3, 27, 11, { name: 'Steven' }]
  3. i=4时,元素是对象(非数字),执行splice(4,1),数组长度变为4,i自增到5,此时i < arr.length不成立,循环结束,所有非数字元素都被处理完毕。

解决方法

方法1:倒序遍历

从数组末尾开始遍历,即使删除元素,前面的元素索引不受影响,不会出现跳过的情况:

let arr = [1, "5", 3, 27, undefined, { name: 'Steven' }, 11];
for (let i = arr.length - 1; i >= 0; i--) {
    if (typeof arr[i] !== 'number') {
        arr.splice(i, 1);
    }
}
console.log(arr); // [1, 3, 27, 11]

方法2:使用filter方法(推荐)

filter方法会返回一个新数组,包含所有符合条件的元素,逻辑更直观且不会修改原数组:

let arr = [1, "5", 3, 27, undefined, { name: 'Steven' }, 11];
const numArr = arr.filter(item => typeof item === 'number');
console.log(numArr); // [1, 3, 27, 11]

内容的提问来源于stack exchange,提问作者andrijadenic9

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 23:15:54