如何为JavaScript集定制对象相等

新的ES 6(和谐)引入了新的Set对象。 Set使用的身份algorithm类似于===运算符,因此不太适合比较对象:

 var set = new Set(); set.add({a:1}); set.add({a:1}); console.log([...set.values()]); // Array [ Object, Object ] 

如何自定义Set对象的相等性以便进行深度对象比较? 有没有像Java equals(Object)

ES6 Set对象没有任何比较方法或自定义比较可扩展性。

.has() .add().delete()方法只能工作在相同的实际对象或相同的原始值上,并且没有办法插入或replace该逻辑。

你大概可以从Set派生自己的对象,并用一些深入的对象比较来replace.has() .add().delete()方法,以便find该对象是否已经在Set中,但是性能可能不太好,因为底层的Set对象根本没有帮助。 在调用原始的.add()之前,您可能必须通过所有现有对象进行强制迭代,以使用自定义比较来find匹配项。

这里有一些来自这篇文章和 ES6function的讨论 :

5.2为什么我不能configuration映射和集合如何比较键和值?

问题:如果有一种方法来configuration哪些映射键和哪些设置元素被认为是相等的,那将是非常好的。 为什么不在那里?

答:这个function已经推迟了,因为很难正确有效地执行。 一种select是将callback交给指定相等的集合。

Java中的另一个选项是通过对象实现(Java中的equals())的方法来指定相等。 但是,这种方法对于可变对象来说是有问题的:一般来说,如果一个对象发生变化,集合中的“位置”也必须改变。 但是这不是在Java中发生的事情。 JavaScript可能会成为比较安全的途径,只能通过值来为特殊的不可变对象(所谓的值对象)进行比较。 按价值进行比较意味着如果内容相同,则两个值被认为是相等的。 原始值在JavaScript中通过值进行比较。

正如jfriend00的答案中所提到的 ,平等关系的定制可能是不可能的

以下代码提供了计算效率(但是内存昂贵)的解决方法

 class GeneralSet { constructor() { this.map = new Map(); this[Symbol.iterator] = this.values; } add(item) { this.map.set(item.toIdString(), item); } values() { return this.map.values(); } // ... } 

每个插入的元素必须实现返回string的toIdString()方法。 当且仅当它们的toIdString方法返回相同的值时,两个对象被认为是相等的。

为了在这里添加答案,我继续实现了一个Map包装器,它接受一个自定义哈希函数,一个自定义的相等函数,并存储具有相同(自定义)哈希值的不同值。

可以预料的 是 ,它比czerny的string连接方法 慢 。

完整的源代码在这里: https : //github.com/makoConstruct/ValueMap