双重for循环去重的核心是外层遍历元素,内层检查其后是否重复;未重复则保留首次出现项。虽逻辑清晰但性能差,大数据量时慢;现代推荐Set或filter+indexOf。

用双重 for 循环实现数组去重,核心思路是:外层循环遍历每个元素,内层循环检查该元素在它之后(或之前)是否已出现过;若未重复,就保留。
基础写法:保留首次出现的元素
这是最常见、逻辑最清晰的方式。遍历当前元素时,只跟它后面的元素比较;如果后面没找到相同值,说明它是“第一次出现”,就推入新数组。
- 外层
i从0到arr.length - 1 - 内层
j从i + 1开始,检查是否和arr[i]相等 - 若内层一轮比较都没匹配上,说明
arr[i]是唯一/首次出现,加入结果数组
示例代码:
function uniqueByDoubleLoop(arr) {
const result = [];
for (let i = 0; i < arr.length; i++) {
let isDuplicate = false;
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] === arr[i]) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
result.push(arr[i]);
}
}
return result;
}
<p>console.log(uniqueByDoubleLoop([1, 2, 2, 3, 1])); // [2, 3, 1]
⚠️注意:这个版本结果顺序是“倒序去重”——保留的是每个值最后一次出现的位置。如果要保留首次出现的顺序(如 [1, 2, 3]),需换种判断方式。
改进写法:按首次出现顺序保留
改为内层循环检查当前元素 arr[i] 在 0 到 i-1 范围内是否已存在。这样只要前面没出现过,就说明是首次。
- 外层
i正常遍历 - 内层
j从0到i - 1,查arr[j] === arr[i] - 若没找到,
arr[i]就是首次出现,推入结果
示例代码:
function uniqueByFirstOccur(arr) {
const result = [];
for (let i = 0; i < arr.length; i++) {
let isFirst = true;
for (let j = 0; j < i; j++) {
if (arr[j] === arr[i]) {
isFirst = false;
break;
}
}
if (isFirst) {
result.push(arr[i]);
}
}
return result;
}
<p>console.log(uniqueByFirstOccur([1, 2, 2, 3, 1])); // [1, 2, 3]
兼容性考虑:处理对象或复杂类型
上述写法基于 === 比较,对对象、数组等引用类型无效(两个字面量相同的对象也不相等)。若需深比较去重,需额外实现判断逻辑,比如用 JSON.stringify(仅限可序列化结构)或递归比对。
- 简单场景可用:
JSON.stringify(obj1) === JSON.stringify(obj2) - 但要注意:属性顺序不同会导致字符串不同;函数、undefined、Symbol 会被忽略或报错
- 生产环境建议用专门的深比较工具(如 Lodash 的
isEqual)
性能提醒:仅适合小数据量
双重循环时间复杂度是 O(n²),数组稍大(比如 > 1000 项)就会明显变慢。现代开发中更推荐:
- 用
Set:[...new Set(arr)](最简、高效、ES6+) - 用
filter + indexOf:arr.filter((item, i) => arr.indexOf(item) === i) - 需要兼容老浏览器时,再考虑双循环,但应加长度校验避免卡顿


















