数组去重无唯一解,应据兼容性、数据类型和性能选方案:es6 set适用于基础类型且高效;ie等旧环境用indexof+循环;对象/nan需自定义逻辑;splice双重循环仅作教学参考。

数组去重没有“唯一正确解”,选哪种方法取决于你的环境兼容性要求、数据类型特征和性能敏感度。ES6 的 Set 是当前最推荐的默认方案,但遇到特殊值(如 NaN、对象、函数)或需支持老旧浏览器时,就得切换策略。
基础类型直接用 Set 最简洁高效
对数字、字符串、布尔值这类基础类型,new Set() 配合扩展运算符或 Array.from() 是首选:
[...new Set([1, 2, 2, 3])] → [1, 2, 3]Array.from(new Set(['a', 'b', 'a'])) → ['a', 'b']
它时间复杂度接近 O(n),代码可读性强,且天然跳过重复项——不需要手动比对或索引查找。
需要兼容 IE 或低版本浏览器时用 indexOf + 循环
ES5 环境下,新建空数组 + indexOf() 判断是最稳妥的通用方案:
- 遍历原数组,若新数组中尚未存在当前元素,就推入
- 能正确处理
undefined、null、0、false等假值(因为用的是严格比较) - 注意:
indexOf()对NaN返回 -1,所以NaN会被当成不重复项多次保留
含对象、函数或 NaN 时得用自定义逻辑
Set 和 indexOf() 都无法识别两个结构相同但内存地址不同的对象,比如 {a:1} 和 {a:1} 总是被视为不同项:
- 若需按结构去重,可用
JSON.stringify()作键(仅适用于纯对象、无函数/undefined/循环引用) - 更健壮的做法是用
Map存储序列化后的键,或借助 Lodash 的uniqBy按特定字段判断 - 处理
NaN:ES6 中Set能识别唯一一个NaN;而indexOf()不行,可改用includes()(ES7)或手写isNaN()判断
慎用 splice + 双重循环,仅作教学参考
虽然很多教程以双重 for + splice() 开头,但它有明显缺陷:
- 直接修改原数组,副作用强
- 删除元素后索引错位,必须手动
j--补偿,易出错 - 时间复杂度 O(n²),大数据量时性能急剧下降
- 对
NaN、{}完全无效(NaN === NaN为 false,对象引用永远不等)
除非明确要求原地修改且数据极小,否则不建议在生产环境使用。











