new Set([1, 1, 2]) 只存两个值,因其使用 SameValueZero 算法自动去重(NaN 与 NaN 视为相等,而 === 不等);对象、函数、Symbol 按引用判重;字符串与数字不自动转换,'1' 与 1 被视为不同值。

JavaScript 的 Set 是一个内置对象,用来存储唯一值——值本身决定是否重复,不依赖键名,也不做类型宽松比较(NaN 和 NaN 被视为相等)。
为什么 new Set([1, 1, 2]) 只存两个值?
因为 Set 在插入时自动去重:它用 SameValueZero 算法比较值(类似 ===,但 NaN === NaN 为 false,而 Set 认为它们相等)。
-
new Set([1, '1', true, {}, {}])长度是5:原始值和对象引用各自独立判断 -
new Set([NaN, NaN])长度是1:这是Set特有的行为,和===不同 - 对象、函数、
Symbol按引用判重:const a = {}; new Set([a, a])长度仍为1
Set 和数组去重哪个更快?
小数据量(Set 构造 + 扩展运算符转回数组([...new Set(arr)])通常比 filter + indexOf 快 2–5 倍,因 Set 内部是哈希表查找(O(1) 平均),而 indexOf 是 O(n) 线性扫描。
- 避免写
arr.filter((v, i) => arr.indexOf(v) === i)处理长数组 - 慎用
Array.from(new Set(arr)):和[...new Set(arr)]行为一致,但稍慢一点(多一次构造) - 如果只需判断存在性(不转回数组),直接用
set.has(x),别绕一圈转成数组再includes
哪些操作会意外破坏唯一性?
不是 Set 本身的问题,而是你没意识到值的“相等性”边界:
立即学习“Java免费学习笔记(深入)”;
- 对象字面量每次都是新引用:
new Set([{a:1}, {a:1}]).size === 2—— 即使内容相同,也存两个 - 日期、正则等对象同理:
new Set([/a/, /a/]).size === 2 - 字符串和数字不会自动转换:
new Set(['1', 1]).size === 2('1' !== 1) - 修改已加入
Set的对象属性,不影响其在Set中的存在或去重逻辑(引用没变)
真正容易被忽略的是:你想去重“逻辑上相同”的对象(比如有相同 id 的用户),Set 做不到——得先用 Map 或 filter + 自定义比较,Set 只认引用或原始值相等。











