JavaScript中forEach内调用Array.splice出现意外结果的问题排查
问题分析与解决方案
首先得说清楚你遇到的问题根源:你的代码里用了splice修改原数组,同时又在遍历原数组的副本索引,这导致索引和原数组的实际元素位置错位了,才出现了剩余元素不符合预期的情况。
原代码的问题拆解
排序后的数组a是[1,2,3,5],你用a.slice()得到了一个和原数组一模一样的副本,然后forEach遍历这个副本:
- 第一次循环
ind=0,splice(0,1)删掉了原数组的第一个元素1,此时a变成[2,3,5]; - 第二次循环
ind=1,但此时原数组长度已经变成3了,splice(1,1)删掉的是3,a变成[2,5]; - 第三次循环
ind=2,原数组长度只有2,splice(2,1)根本找不到这个位置,不会有任何操作; - 第四次循环
ind=3,同样超出了原数组的长度,也没效果。
所以最后剩下[2,5],这完全是因为索引错位导致的。
符合你需求的正确实现
你的核心需求是:排序后,每个元素x只和它后面的元素y比较一次(避免y和x重复比较),其实不需要用splice这种会修改原数组的操作,直接用两层循环就能轻松实现:
var a = [1, 3, 2, 5]; a.sort((b, c) => b - c); // 排序后得到 [1,2,3,5] // 外层循环:遍历到倒数第二个元素即可 for (let i = 0; i < a.length - 1; i++) { const x = a[i]; // 内层循环:只遍历x之后的所有元素 for (let j = i + 1; j < a.length; j++) { const y = a[j]; console.log(`正在比较 x: ${x} 和 y: ${y}`); // 在这里写你的比较逻辑,比如对象属性对比之类的操作 // 比如 if (x.someProperty > y.someProperty) { ... } } }
这段代码会依次比较(1,2)、(1,3)、(1,5)、(2,3)、(2,5)、(3,5),完全满足“只比较一次,不重复”的要求,而且不会修改原数组,逻辑清晰易懂。
如果之后你需要处理对象数组,也只需要把x和y替换成对象的属性即可,比如:
const objArr = [{val:3}, {val:1}, {val:2}]; objArr.sort((b,c) => b.val - c.val); for (let i = 0; i < objArr.length -1; i++) { const x = objArr[i]; for (let j = i+1; j < objArr.length; j++) { const y = objArr[j]; console.log(`比较x.val: ${x.val} 和 y.val: ${y.val}`); // 这里写对象属性的对比逻辑 } }
内容的提问来源于stack exchange,提问作者thenninger
相关产品推荐
相关产品推荐

