新的 ES 6 (Harmony) 引入了新的 Set 对象。 Set 使用的身份算法类似于 ===
运算符等不太适合比较对象:
var set = new Set();
set.add({a:1});
set.add({a:1});
console.log([...set.values()]); // Array [ Object, Object ]
如何自定义 Set 对象的相等性以便进行深度对象比较?有没有类似 Java equals(Object)
东西?
原文由 czerny 发布,翻译遵循 CC BY-SA 4.0 许可协议
更新 3⁄2022
目前有一个 提议 将 Records 和 Tuples(基本上是不可变的对象和数组)添加到 Javascript。在该提案中,它使用
===
或!==
提供记录和元组的直接比较,它比较值,而不仅仅是对象引用和与此答案相关的Set
和Map
对象将在键比较/查找中使用 Record 或 Tuple 的 值,这将解决此处所要求的问题。由于 Records 和 Tuples 是不可变的(无法修改)并且因为它们很容易按值进行比较(通过它们的内容,而不仅仅是它们的对象引用),它允许 Maps 和 Sets 使用对象内容作为键和明确提出的规范将此功能命名为 Sets 和 Maps。
这个原始问题要求 Set 比较的可定制性,以支持深度对象比较。这不建议 Set 比较的可定制性,但如果您使用新的 Record 或 Tuple 而不是 Object 或 Array,它直接支持深度对象比较,从而解决这里的原始问题。
请注意,该提案已于 2021 年年中进入第二阶段。它最近一直在向前推进,但肯定没有完成。
Mozilla 在这个新提案上的工作可以在 这里 追踪。
原始答案
ES6
Set
对象没有任何比较方法或自定义比较扩展性。.has()
,.add()
和.delete()
方法只适用于它是相同的实际对象或意味着不具有相同的原始值或者只替换那个逻辑。You could presumably derive your own object from a
Set
and replace.has()
,.add()
and.delete()
methods with something that did a deep object comparison首先要查找该项目是否已经在 Set 中,但性能可能不会很好,因为底层Set
对象根本没有帮助。在调用原始.add()
之前,您可能只需要对所有现有对象进行强力迭代以使用您自己的自定义比较找到匹配项。以下是 本文中的一些信息以及对 ES6 功能的讨论: