我正在尝试了解节点js中发生的情况,我无法弄清楚它为什么会发生。
假设我有下一个代码:
let obj = {x:1,y:2};
let arr = [obj, obj, obj, obj, obj], otherArr = [];
for(let i = arr.length - 1; i >=0; i--){
let objInLoop = arr[i];
if(objInLoop.x >= 0){ // <= this line throws an exception: Cannot read property 'x' of undefined
otherArr.push(objInLoop);
delete arr[i];
}
}
我得到的错误是在代码的第6行,异常说明objInLoop是undefined
,我无法理解它是怎么回事。
很明显,我每个循环都从数组中删除一个元素,但是循环从结尾开始,所以每个delete
都不应该影响下一个循环。
当我调试那种情况时,我看到当弹出异常时,i
变量的值小于当前arr
长度(长度有1个元素和{ {1}}在值中显示1。
这种情况并非一直发生,但它突然出现了几次,i
条件中的0
实际上是一个变量,并不总是具有删除元素的真实结果。所有代码都更大,包含许多其他功能和事件。但是'从数组中删除元素'只出现在我在这里展示的for循环部分中。其他异步代码段有一个push元素,可以向元素添加元素。
我知道我可以通过向if
添加确保if
的条件来避免这种情况。但重点是我无法理解这种异常是如何发生的。
答案 0 :(得分:3)
如果数组中存在间隙,则会发生这种情况。如果您将arr
的作业更改为let arr = [obj, obj,, obj, obj], otherArr = [];
,则可以看到此内容。
如何在阵列中出现间隙?好吧,有一件事可能会导致它是因为数组之前已经完成了循环并删除了东西。
let arr = [{}, {}, {}];
console.log(arr[1]); // {}
delete arr[1];
console.log(arr[1]); // undefined
console.log(arr); // [ {}, <1 empty item>, {} ]
如果delete
是你真正想要的,如果数组可能不止一次通过循环,那么你需要检查undefined.
或者,如果对象的索引可以更改,则可以使用Array.prototype.splice()
。
let arr = ['a', 'b', 'c', 'd'];
let i = 2;
arr.splice(i, 1); // remove one item at index i, i is 2, arr[i] is 'c'
console.log(arr); // ['a', 'b', 'd']
或者您可以完全放弃循环并使用Array.prototype.filter()
,Array.prototype.map()
,Array.prototype.forEach()
,具体取决于哪种情况适合您的情况。