javascript - 如何自定义JavaScript集合的对象相等性

新的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)

时间:

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

.has().add().delete() 方法只能作为原语的实际对象或者相同的值,而不用插入或者替换逻辑。

如果项目已经在集合中,但是性能可能不是很好,那么你可以从 Set.add().delete() 方法派生出自己的对象,从而找到一个新的对象。 你可能需要在所有现有的对象中执行一个蛮力迭代,在调用原始 .add() 之前使用你自己的自定义比较查找匹配。

以下是来自的一些信息和讨论的特性:

5.2 为什么不能配置映射和集比较键和值

问:如果有一种方法配置什么map键,哪些set元素被认为是相等的,这将是很好的。 为什么不在那里?

答:该特性已经被推迟,因为它很难实现正确和高效。 一个选项是对指定相等性的集合进行回调。

在Java中,另一个选项是通过在Java中实现( 等于( equals ) ) 来指定相等性的方法。 但是,对于可变对象,这种方法是有问题的: 通常,如果对象发生更改,则集合中的"location "也必须更改。 但这并不是在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();


 }



 delete(item) {


 return this.map.delete(item.toIdString());


 }



//...


}



每个插入的元素都必须实现返回字符串的toIdString() 方法。 如果两个对象的toIdString 方法返回相同值,则认为它们相等。

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

不出所料,它比czerny连接方法( ) 更慢,它比字符串

完整来源:https://github.com/makoConstruct/ValueMap

...