【逆战班】
通常我们在删除某个父元素下的若干子元素的时候 习惯使用for循环遍历来实现,但是下面这种情况就有点不好使了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> var arr = [1,1,1,2,2,2,3,3,3,4,4,4,5,5,5]; function setNewArr2(arr){ // 外层循环,从第一个数值开始,循环至最后一个数值 for(var i = 0 ; i <= arr.length-1 ; i++){ // 内层循环,从当前起始数值的下一个数值开始,循环至最后一个数值 for(var j = i+1 ; j <= arr.length-1 ; j++){ if(arr[i] === arr[j]){ arr.splice(j,1); } } } return arr; } var newArr = setNewArr2(arr); console.log(newArr); </script> </body> </html>
这是一个实现去重的操作,理想情况下是把重复的内容去掉
下面是运行结果:
但是并没有达到我们想要的结果,我们发现 , 虽然 使用了 for 循环,但是并没有实现效果 , 这是为什么呢 ?因为在执行过程中这个数组坍塌了。
数组坍塌现象:在对数组进行操作的时候,会使数组的长度产生变化,同时操作的数组那个项的下一个索引会被跳过,从而造成数组的某项会被跳过,这种叫做数组塌陷现象。
就拿这个数组中的数字1来说:
我们原本的目的是保留第一个1,删除后面两个1,但是实际却只删除了一个。
遍历到第二个1,索引值i是1,执行删除操作,此时数组的长度就从原来的15变成了14,索引值还是1.
在进行循环 i++,这时i 变成 2,但是原来没删除数组中的第二个1索引值变成了1,这样再去执行 i = 2的操作,这样就跳过了原来没删除数组中的第二个1,去执行后面的操作,从而造成了输出的结果会有一个1没有被删除,就形成了数组塌陷现象。后面其他数字也是同一原理。
解决办法:
就是在对数组某项进行操作之后,手动将索引值 i --,保持数组每一项都被遍历。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> var arr123 = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5]; function setNewArr2(arr) { // 外层循环,从第一个数值开始,循环至最后一个数值 for (var i = 0; i <= arr.length - 1; i++) { // 内层循环,从当前起始数值的下一个数值开始,循环至最后一个数值 for (var j = i + 1; j <= arr.length - 1; j++) { if (arr[i] === arr[j]) { // 执行删除数组单元操作,之后的单元,会前移,顶替当前位置的单元 // 此时,当前位置就是放置了一个新的单元 // 这个位置就必须要重新操作一次,判断数值是否相同 arr.splice(j, 1); // 先将循环生成的索引--, 在执行循环的++ // 等于操作之后,索引值没有变,下次循环,执行的对象,仍然是当前这个单元 j--; } } } return arr; } var newArr = setNewArr2(arr123); console.log(newArr); </script> </body> </html>
执行结果: