Set是ES6引入的唯一值集合,存储值唯一且不强制类型转换,5和"5"视为不同;去重数组用[...new Set(arr)],但对象需手动按字段处理,NaN和+0/-0在Set中自动去重。

Set 是什么:JavaScript 里的唯一值集合
Set 是 ES6 引入的内置构造函数,它存储的值必须是唯一的(重复值会被自动忽略),且不强制类型转换——5 和 "5" 被视为不同值。
它不是数组,没有索引,不能用 [0] 取值;也不支持 map/filter 等数组方法,但提供 .add()、.has()、.size、.values() 等接口。
用 Set 去重数组:最简写法与注意事项
把数组转成 Set,再转回数组,是最常见的去重方式:
const arr = [1, 2, 2, 3, "3", 4, 4, 5]; const uniqueArr = [...new Set(arr)]; // [1, 2, 3, "3", 4, 5]
这个写法简洁,但要注意以下几点:
-
[...new Set(arr)]依赖展开运算符,IE 不支持;如需兼容旧环境,得用Array.from(new Set(arr)) - Set 对象只对原始值(string/number/boolean/symbol/null/undefined)做严格相等判断;
{a:1}和{a:1}仍被视为两个不同对象,不会去重 - 去重后顺序保持原数组首次出现的顺序,这点比用
filter() + indexOf()更可靠
对象数组去重不能直接用 Set?得手动处理
Set 对对象引用敏感,两个结构相同但内存地址不同的对象,new Set([{a:1}, {a:1}]) 会保留两者。要去重对象数组,得先提取唯一标识(如 id 字段)或序列化比较:
立即学习“Java免费学习笔记(深入)”;
const users = [{id: 1, name: "Alice"}, {id: 2, name: "Bob"}, {id: 1, name: "Alice"}];
const seen = new Set();
const uniqueUsers = users.filter(item => {
if (seen.has(item.id)) return false;
seen.add(item.id);
return true;
}); // [{id: 1, name: "Alice"}, {id: 2, name: "Bob"}]
常见错误是直接写 [...new Set(users)],结果毫无变化——因为每个对象都是新引用。
性能和边界情况:大数组、NaN、+0/-0
Set 去重平均时间复杂度是 O(n),比双层循环的 O(n²) 快得多,适合几千项以内的数组。但仍有几个容易被忽略的细节:
-
NaN在 Set 中只算一个值:new Set([NaN, NaN]).size === 1,这是它比===更“合理”的地方 -
+0和-0在 Set 中被视为相等:new Set([+0, -0]).size === 1,这与Object.is()一致,但不同于=== - 如果数组含大量嵌套对象或函数,Set 本身不报错,但去重无效——得确认你真正想比较的是什么
别指望 Set 自动理解业务语义;它只认内存引用或原始值相等性。对象去重、深比较、按字段筛选,都得自己加逻辑。











