JavaScript Set 使用 SameValueZero 算法判断重复,NaN 和 ±0 被视为相同,对象按引用比较,无键概念,仅存值,不支持下标访问,去重对象数组需手动处理唯一标识。
JavaScript Set 是一个内置构造函数,用来创建元素唯一、无序的集合。它不基于键值对,也不允许重复值——哪怕两个值在 JavaScript 中“相等”,Set 也会按 SameValueZero 算法判断是否重复,这意味着 NaN 和 NaN 被视为相同,而 +0 和 -0 也被视为相同(这点和 Object 的键不同)。
Set 内部使用 SameValueZero 比较算法,不是 ===,也不是 Object.is()(虽然非常接近)。关键行为包括:
NaN 只会被存一次:const s = new Set([NaN, NaN]); s.size // 1
+0 和 -0 被视为同一个值:const s = new Set([+0, -0]); s.size // 1
const a = {x: 1}; const b = {x: 1}; new Set([a, b]).size // 2new Set([1, new Number(1)]).size // 2
和 Map 或普通对象不同,Set 没有“键”概念。它只维护一个值列表,每个值既是“键”也是“值”。这带来几个实际影响:
set[key] 访问,必须用 set.has(value) 查询存在性Object.keys() 的原生键枚举方法;遍历靠 fo
r...of、set.values() 或展开运算符 [...set]
const s = new Set(); s.add(42); s.add(42); s.size // 1
直接把对象放进 Set 不会按属性去重,因为对象比较看引用。如果要按结构去重,必须先序列化或提取唯一标识:
const arr = [{id: 1}, {id: 1}]; const unique = [...new Set(arr)]; // length === 2const arr = [{id: 1}, {id: 1}, {id: 2}]; const seen = new Set(); const unique = arr.filter(item => { if (seen.has(item.id)) return false; seen.add(item.id); return true; });真正容易被忽略的是:Set 的“唯一性”完全依赖运行时的值表示,不是开发者语义上的“相同”。一旦你混用原始值和包装对象、或依赖对象结构而非引用,就很容易以为去重了,其实没生效。