JavaScript中过滤数组时出现Uncaught TypeError读取length报错的原因
错误原因分析及修复方案
先看你的代码:
function filteredArray(arr, elem) { for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr[i].length; j++) { if (arr[i][j] === elem) { arr.splice(i, 1); } } } return newArr = [...arr]; } console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
为什么if条件会引发错误?
核心问题出在遍历数组时用splice修改了原数组长度,具体触发流程:
- 外层循环依赖
arr.length判断是否继续,当你执行arr.splice(i, 1)删除当前子数组后,原数组的长度会直接减1,后续元素自动向前移动一位。 - 但循环变量
i仍会正常递增,比如原数组初始长度是4,删除第一个元素后长度变成3,当i递增到3时,arr[3]已经是undefined(因为数组现在只有3个元素,索引最大是2),此时内层循环访问arr[i].length,自然会抛出Cannot read properties of undefined (reading 'length')的错误。
为什么移除if条件后错误消失?
移除if条件后,splice代码不会执行,原数组的长度从头到尾都没有变化,arr[i]始终是有效的子数组,不会出现undefined的情况,所以访问arr[i].length不会报错。
修复方案
推荐两种更可靠的写法:
方案1:使用filter方法(最简洁)
直接过滤掉包含目标元素的子数组,不需要修改原数组:
function filteredArray(arr, elem) { return arr.filter(subArr => !subArr.includes(elem)); }
方案2:倒序遍历原数组
倒序遍历可以避免删除元素后索引错乱的问题,因为删除当前元素不会影响前面未遍历的元素:
function filteredArray(arr, elem) { // 从数组末尾往前遍历 for (let i = arr.length - 1; i >= 0; i--) { if (arr[i].includes(elem)) { arr.splice(i, 1); } } return [...arr]; }
内容的提问来源于stack exchange,提问作者Divinej
相关产品推荐
相关产品推荐

