新しいES 6(Harmony)は新しいセットオブジェクト。Set で使用されるアイデンティティ アルゴリズムは演算子に似ているため===
、オブジェクトの比較にはあまり適していません。
var set = new Set();
set.add({a:1});
set.add({a:1});
console.log([...set.values()]); // Array [ Object, Object ]
オブジェクトの詳細な比較を行うために、Set オブジェクトの等価性をカスタマイズするにはどうすればよいでしょうか? Java のようなものはありますかequals(Object)
?
ベストアンサー1
2022年3月更新
現在、提案レコードとタプル (基本的には不変のオブジェクトと配列) を Javascript に追加します。その提案では、またはを使用してレコードとタプルを直接比較し、オブジェクト参照だけでなく値を比較します。また、この回答に関連して、およびオブジェクトの両方が===
キーの比較/検索でレコードまたはタプルの値を使用するため、ここで求められている問題が解決されます。!==
Set
Map
レコードとタプルは不変 (変更不可) であり、値 (オブジェクト参照だけでなく、その内容) で簡単に比較できるため、マップとセットはオブジェクトの内容をキーとして使用できます。提案された仕様では、この機能をセットとマップに対して明示的に指定しています。
この元の質問では、ディープ オブジェクト比較をサポートするために、Set 比較のカスタマイズ可能性を求めていました。これは、Set 比較のカスタマイズ可能性を提案するものではありませんが、オブジェクトまたは配列の代わりに新しいレコードまたはタプルを使用する場合、ディープ オブジェクト比較を直接サポートするため、ここでの元の問題が解決されます。
なお、この提案は 2021 年半ばにステージ 2 に進みました。最近は前進していますが、まだ完了したわけではありません。
この新しい提案に関するMozillaの取り組みは追跡できる。ここ。
公式仕様草案ここ。
不完全なポリフィルここ。
仕様では新しい言語機能が使用され、言語に新しい型が実装されるため、ポリフィルが完全なポリフィルになることは決してないことに注意してください。ただし、いくつかの回避策を講じることでポリフィルを使用することはできます。
元の回答
ES6Set
オブジェクトには、比較メソッドやカスタム比較拡張機能はありません。
.has()
、、.add()
およびメソッド.delete()
は、プリミティブの実際のオブジェクトまたは値が同じである場合にのみ機能し、そのロジックにプラグインしたり置き換えたりする手段はありません。
おそらく、 から独自のオブジェクトを派生させSet
、.has()
、.add()
メソッドを、.delete()
最初にオブジェクトを詳細に比較してアイテムがすでに Set 内にあるかどうかを確認するものに置き換えることができますが、基礎となるSet
オブジェクトがまったく役に立たないため、パフォーマンスはおそらく良くないでしょう。おそらく、元の を呼び出す前に、独自のカスタム比較を使用して一致するものを見つけるために、既存のすべてのオブジェクトに対してブルート フォース反復処理を実行する必要があるでしょう.add()
。
以下は情報ですこの記事と議論ES6の機能:
5.2 マップとセットがキーと値を比較する方法を設定できないのはなぜですか?
質問: どのマップ キーとどのセット要素が等しいとみなされるかを設定する方法があれば便利です。なぜないのですか?
回答: その機能は、適切かつ効率的に実装するのが難しいため、延期されています。 1 つのオプションは、等価性を指定するコレクションにコールバックを渡すことです。
Java で利用できるもう 1 つのオプションは、オブジェクトが実装するメソッド (Java では equals()) を介して等価性を指定することです。ただし、この方法は可変オブジェクトでは問題があります。一般に、オブジェクトが変更されると、コレクション内のその「場所」も変更される必要があります。しかし、Java ではそうはなりません。JavaScript はおそらく、特別な不変オブジェクト (いわゆる値オブジェクト) に対してのみ値による比較を有効にするという、より安全な方法を採用するでしょう。値による比較とは、2 つの値の内容が等しい場合に、それらの値が等しいとみなされることを意味します。JavaScript では、プリミティブ値は値によって比較されます。