需求:先将对象属性num的值不为0的添加一个新属性pub,然后将没有pub属性的对象删除。
正常代码实现如下:
//data中的数据源:
msg:[{num:0},{num:4},{num:0,pub:'a'},{num:0},{num:0},{num:6}]
//正常的实现的方法:
//1.不为0的值添加新属性
for(let item of this.msg){
if(item.num!=0){
item.pub='new';
}
};
//2.过滤出num不为0的对象,进行赋值
let filterMsg=this.msg.filter(item=>item.pub)
this.msg=filterMsg
//简化的写法(虽然不规范但也能实现效果)
this.msg=this.msg.filter((item,index,arr)=>{
if(item.num!=0){
arr[index]['pub']='new'
}
return item.pub
});
因为想看看还有没有其他方法可以实现,因此采用了forEach+splice方法
代码如下:
// 不为0的值添加新属性
for(let item of this.msg){
if(item.num!=0){
item.pub='new';
}
};
this.msg.forEach((item,index) => {
if(!item.pub){
this.msg.splice(index,1)
}
});
按正常的逻辑来说,上面代码是可行的,但为何效果是下面这样的。
我们来看下面这张图的解释。
splice导致遍历的元素发生了变化,但是前面两次都没有什么问题。第三次的时候遍历的索引为2,删除该元素之后,后面还有一个num值为0的元素,这个元素的索引变为了2,但由于索引为2的元素已经遍历过了,因此遍历索引为3的元素,最后存在pub属性,因此产生了这个bug。
总结:在vue里面虽然splice是响应式的,但是不建议与forEach连用,一般来讲forEach无法中断遍历,当需要过滤数据的时候还是采用filter比较好,需要修饰数组(不删减数组)的时候采用map遍历比较好。