我有一个案例,我需要遍历一个对象数组,检查每个元素的条件,删除现有的对象&根据条件的结果添加新对象。我目前的代码如下,但当然它不起作用。
在某些迭代中添加/删除新元素时迭代数组的正确方法是什么。
var arrayOfObjects = [] // a list to store objects of the same time
for(var i = 0; i < 5; i++){
arrayOfObjects.push(new someClass());
}
while(true){
for(var obj in arrayOfObjects){
// some conditional check on obj
// if check is true, delete the obj from array & add a new object
arrayOfObjects.splice(arrayOfObjects.indexOf(obj),1);
arrayOfObjects.push(new someClass());
}
}
答案 0 :(得分:4)
在迭代过程中修改对象/数组是一个反模式。后果是不可预测的。例如。循环也会在新添加的项目上进行迭代,并且可能会在每次迭代时添加新项目。因此存在无限循环。
更好的解决方案是将项目复制/添加到新的空对象/数组中。
var result = [];
arrayOfObjects.forEach(function(obj) {
if(isCopyRequired(obj)) {
result.push(obj);
}
if(isNewObjectRequired(obj)) {
result.push(new someClass());
}
});
&#13;
答案 1 :(得分:2)
&#34;正确&#34;迭代数组的方法是使用for循环,因为for..in遍历所有可枚举属性(拥有和继承)并且不保证顺序,因此可能需要进行额外的检查。 for..in对于稀疏数组很有用,但它们并不常见。
在数组中删除元素或它们的顺序似乎没有任何理由。要删除它们,您需要做的就是将一些其他对象的引用分配给它们在数组中的索引,例如
while(true){
你真的希望这个永远循环吗?我想你应该删除 while 块。
for (var i=0, iLen=arrayOfObjects.length; i<iLen; i++) {
// some conditional check on obj
// if check is true, delete the obj from array & add a new object
if (check) {
arrayOfObjects[i] = new someClass();
}
}
这里的主要区别是你的原始代码会在数组的末尾添加新对象,而这个verison会将新对象添加到与旧对象相同的索引处。
您还可以使用 forEach :
arrrayOfObjects.forEach(function(value, index) {
// do check on value
if (check) arrayOfObjects[i] = new someClass();
});
答案 2 :(得分:2)
如果确实需要将新对象添加到数组的末尾
for(var obj = 0; obj < arrayOfObjects.length; obj += 1){
var index;
// some conditional check on obj
// if check is true, delete the obj from array & add a new object
if(somecondtion) {
var index = arrayOfObjects.indexOf(obj);
arrayOfObjects.splice(index, 1);
arrayOfObjects.push(new someClass());
if (index <= obj) {
obj -= 1;
}
}
}
如果删除的项目在数组中处于当前位置(obj
)或更早,则从obj
中减去一,这实际上意味着将在下一个数组中检查相同的位置迭代 - 这是切片完成之前的下一个元素