数组去重本质是保留首次出现项、剔除后续重复,需保序且不改原数组;基础类型首选Set,对象数组须按字段或序列化判重。

JS 中数组去重全景解析,核心是看清三点:去重目标是什么、不同数据类型怎么判重、各方法在真实项目里怎么选。
明确去重的本质目标
数组去重不是“删掉所有重复”,而是「保留每个值首次出现的位置,剔除后续重复项」。关键要求是:保序、不改原数组(除非主动修改)、结果可预测。
注意两个常见误区:
- 数字 1 和字符串 "1" 在 JS 中严格不等,不算重复;
- 两个内容相同的对象(如
{id: 1}和{id: 1})内存地址不同,视为不同元素——基础方法默认无法处理这类情况。
基础类型去重:优先用 Set
对数字、字符串、布尔值、null、undefined、NaN 等,Set 是首选:
- 一行写法:
[...new Set(arr)]或Array.from(new Set(arr)); - 自动识别
NaN === NaN(其他方法如indexOf会失败); - 时间复杂度 O(n),性能最优;
- 兼容性需注意:IE 不支持,现代项目基本无压力。
兼容旧环境或需精细控制时的替代方案
当要支持 IE 或需自定义判重逻辑(比如忽略大小写、按某字段比较),可选:
-
filter + indexOf:简洁易读,但indexOf对NaN返回 -1,不适用含NaN的场景; -
for + includes:支持NaN,逻辑直白,适合小数组; - 对象键名法(
obj[item] = true):效率高,但所有键会被转为字符串,1和"1"会冲突,需加类型前缀(如typeof item + item)来规避。
对象数组去重:不能靠 Set 直接解决
对象本身是引用类型,Set 只认内存地址。去重必须指定依据,常见做法:
- 按单个字段(如
id):用Map缓存已见的id值,遍历时跳过重复; - 按多个字段或全量结构:用
JSON.stringify(item)生成唯一键,再结合Set或对象判重(注意函数、undefined、Symbol 会丢失); - 更稳健方案:用
lodash.uniqBy(arr, 'id')或手写深比较(仅必要时)。











