Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/459.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 关于ES6'的使用,我如何检查类实例的相等性和相同性;什么是集合?_Javascript_Typescript_Ecmascript 6_Set_Typescript Typings - Fatal编程技术网

Javascript 关于ES6'的使用,我如何检查类实例的相等性和相同性;什么是集合?

Javascript 关于ES6'的使用,我如何检查类实例的相等性和相同性;什么是集合?,javascript,typescript,ecmascript-6,set,typescript-typings,Javascript,Typescript,Ecmascript 6,Set,Typescript Typings,我正在尝试通过使用TypeScript使用ES6。我需要了解如何为在应用程序中使用的对象创建。例如,对象如下所示 class Product { metadata: Map<String, String> constructor(id: number) { metadata = new Map<String, String>(); } public addMetadata(key: String, val: String): Product { th

我正在尝试通过使用TypeScript使用ES6。我需要了解如何为在应用程序中使用的对象创建。例如,对象如下所示

class Product {
 metadata: Map<String, String>

 constructor(id: number) { 
  metadata = new Map<String, String>();
 }

 public addMetadata(key: String, val: String): Product {
  this.metadata.set(key, val);
  return this;
 }
}

Set
Map
仅当某个键是完全相同的对象,而不是具有相同内容的不同对象,而是相同的实际对象时,才会认为该键是相同的对象。换句话说,它的工作原理与
obj1===obj2
类似

如果你使用的是一个
集合
,比如你的标题和第一段所指的,那么你就很不走运了。两个具有相同内容的独立对象(或在您的情况下,相同的
.id
属性)将被视为
集中的独立项,因为它们实际上是不同的对象

在这个问题中,您可以看到一个讨论,它是关于
集合是否可自定义的



如果您使用的是
映射
(这似乎是您的代码所引用的,尽管问题的文本中没有这样说),那么您可以使用
.id
属性作为键,对象本身作为值。只要
.id
属性是一个基元(如字符串或数字),那么对于任何给定的
id
您将只能在
映射中获得一个项,而不是直接回答您的问题,但是“标记集”(因为缺少更好的名称)可能比重写的相等运算符工作得更好。这样,“相等”是集合本身的属性,而不是底层对象的属性。下面是一个JS示例:

类SetBy扩展集{
建造师(pred){
超级();
this.pred=pred;
this.inner=新集合();
}
has(obj){
返回this.inner.has(this.pred(obj));
}
添加(obj){
如果(!this.has(obj)){
this.inner.add(this.pred(obj));
super.add(obj);
}
}
}
s=新的立根(x=>x.id);
a={id:1,名称:'a'};
b={id:1,名称:'b'};
c={id:1,名称:'c'};
d={id:2,名称:'d'};
e={id:2,名称:'e'};
s、 添加(a);
s、 添加(b);
s、 添加(c);
s、 加(d);
s、 加(e);
console.log([…s])检查对象是否相等的简单(也是有效)方法是比较
JSON.stringify()
字符串。由于只有自己的可枚举属性是字符串化的,
元数据
属性应该是不可枚举的:

class Product {
 metadata: Map<String, String>

 constructor(public id: number) { 
     Object.defineProperty(this, 'metadata', {
         configurable: true,
         writable: true
     })

     this.metadata = new Map<String, String>(); 
 }
 ...
}
此方法可用于自定义
集合

class ObjectedSet extends Set {
  protected _find(searchedValue) {
    for (const value of Array.from(this.values()))
      if (JSON.stringify(value) === JSON.stringify(searchedValue))
        return searchedValue;
  }

  has(value) {
    return !!this._find(value);
  }

  add(value) {
    if (!this.has(value))
      super.add(value);

    return this;
  }

  delete(value) {
    const foundValue = this._find(value);

    if (foundValue)
      super.delete(foundValue);

    return !!foundValue;
  }
}

我没有一个好的答案,但可以澄清一些事情。在javascript中,非原语的“==”或“==”表示引用相等。因此,它必须是完全相同的实例才能计算为“true”(根本不检查属性)。我还没有对“Set”和“Map”做过太多的研究,但希望这能有所帮助。@Aliester可能是重复的——作为回答另一个问题的人,我并不认为这是重复的。这里的问题完全不同。阅读其他答案可能会给你一些信息,你可以用这些信息来回答这个问题,但是没有人会说这个问题和那个问题是一样的。@如果我误解了,jfriend00表示歉意,但OP本质上不是在问如何使用自定义javascript对象和集合,并提供他自己的自定义相等性计算,而不是本机逻辑吗?不过,我会听从你的意见。@Aliester-首先,OP对他们使用的是
Set
还是
Map
有点困惑。问题的文本指的是
集合
,但代码指的是
地图
。如果他们正在使用
映射
,并且可以将
id
值作为
映射
中的键,那么他们的问题可能会得到解决。让我们先看看结果如何。这种方法忽略了
delete
。实现它不如添加它有趣。
add
@estus:它也可能是一行,否?@georg否,因为您需要从外部集合中删除与被删除对象具有相同谓词的对象。指向外部对象的内部
映射
(而不是
)可能会解决这个问题。@Bergi:有道理。OP实际上在寻找的似乎是映射未设置。字符串序列化听起来像是一种进行等式比较的非常不高效的方法。为什么你认为它很快?“BurgI我会想到的,但是在我自己的基准中,代码> JSON。StrugInt[/COD] >与<代码>的比较。这两种方法都很快,所以这种考虑属于初步优化范畴。如果Lodash不在项目中使用,我会考虑<代码> JSON。StrugIng/<代码>一个无脑的。是的,对于小而相等的输入,我会把它们放在同一个水平上。但是,如果两个输入共享一个大的数据结构(即
.isEqual
可以通过引用标识进行检查),或者是一个大的但不相等的数据结构(即
JSON.stringify
仍然需要完全遍历),我预计会有很大的差异。@Bergi当然。IIRC,stringify在同等对象上的表现略优于isEqual,在不平等对象上的表现略逊于isEqual。在我的用例中,我有一般的小对象(总共10-20个可枚举的道具),性能根本不是问题。
new Product(1) !== new Product(1);
JSON.stringify(new Product(1)) === JSON.stringify(new Product(1));
JSON.stringify(new Product(1)) !== JSON.stringify(new Product(2));
class ObjectedSet extends Set {
  protected _find(searchedValue) {
    for (const value of Array.from(this.values()))
      if (JSON.stringify(value) === JSON.stringify(searchedValue))
        return searchedValue;
  }

  has(value) {
    return !!this._find(value);
  }

  add(value) {
    if (!this.has(value))
      super.add(value);

    return this;
  }

  delete(value) {
    const foundValue = this._find(value);

    if (foundValue)
      super.delete(foundValue);

    return !!foundValue;
  }
}