跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何识别 Set 在处理对象引用时的“深度”限制:为什么不同字面量不被视为重复

Set对对象只比较内存地址而非属性值,因其内部使用SameValueZero算法(与===一致),不调用toString()或valueOf(),也不支持深度比较或自定义相等逻辑。 JavaScript 的
Set
对对象不做“深度比较”,它只认内存地址——两个
{a: 1}
字面量哪怕结构一模一样,也是两个独立对象,分配在不同内存位置,
===
判断为
false
,
Set
就认为它们不重复。 根本原因:Set 依赖 SameValueZero 算法
Set
内部用的是 SameValueZero 比较规则(与
===
基本一致,仅对
+0
/
-0
和
NaN
特殊处理)。该规则对对象只比较引用,不遍历属性、不递归检查嵌套值。所以:
new Set([{x: 1}, {x: 1}])
包含两个元素
new Set([{}, {}])
也包含两个元素 哪怕对象只有 1 层、1 个属性、全是基本类型,只要不是同一引用,就无法去重 为什么不能靠 toString() 或 valueOf() 干预?
Set
完全不调用对象的
toString()
、
valueOf()
或任何自定义方法。这些方法在对象转字符串或数值运算时才起作用,而
Set.has()
或
add()
过程中不会触发它们——这是常见误解来源。 所谓“深度限制”其实是根本没深度 “深度”在这里是误导性说法。
Set
并非“限制在某一层”,而是压根没有设计深度逻辑。它不像 Java 的
HashSet
那样允许重写
hashCode()
和
equals()
,也不像某些库提供比较器参数。它的行为是固定的、底层的、不可覆盖的。 验证方式很简单 只需两行代码就能确认:
const s = new Set(); s.add({a: 1}); console.log(s.has({a: 1})); // false
console.log({a: 1} === {a: 1}); // false
第二行结果直接解释了第一行——
has()
的判断依据就是
===
。

相关文章