ES6のマップとオブジェクト、いつ使用するか?


83

参照:MDNマップ

キーが実行時まで不明であり、すべてのキーが同じタイプであり、すべての値が同じタイプである場合は、オブジェクト上でマップを使用します。

個々の要素を操作するロジックがある場合は、オブジェクトを使用します。

質問:

オブジェクト上でマップを使用する適切な例は何ですか?特に、「実行時までキーが不明になるのはいつですか?」

var myMap = new Map();

var keyObj = {},
    keyFunc = function () { return 'hey'},
    keyString = "a string";

// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

console.log(myMap.get(keyFunc));

ええ、私はそれに気づきました。関数を値として設定します。@JonathanLonowski私がいつそれをすべきか考えていただけますか:(ユースケースを考えるのは難しいです。–
Matthew Harwood

7
オブジェクトの使用にデータを関連付けたいDOM要素を言う場合に使用できます。たとえば、要素のIDをオブジェクトのキーとして使用する代わりに、要素自体をマップのキーとして使用できるため、要素にID(またはオブジェクト参照以外の他の一意の識別子)があるかどうかは関係ありません。 ) か否か。
RobG 2015

1
@RobGはほんの少しの追加です:その場合、それWeakMapも役立つかもしれません。
zerkms 2015

1
これは、オブジェクトをレコードとして、またはマップを他のすべての種類のマッピングに使用することを示唆していると思います。レコードで私はこのようなフィールドを持つユーザオブジェクトとしてフィールドの固定セットを有するデータ構造体を意味nameし、idたとえば。
Felix Kling 2015

1
私がそのMDNページを読んでいたとき、ユースケースの箇条書きリストはあなたが引用した段落よりもはるかに役に立ちました。確かにあなたのタイトルで提起された質問に関連して。
CodingIntrigue 2015

回答:


51

オブジェクト上でマップを使用する適切な例は何ですか?

すでに1つの良い例を挙げていると思います。Mapオブジェクト(関数オブジェクトを含む)をキーとして使用する場合は、少なくともsを使用する必要があります。

特に、「実行時までキーが不明になるのはいつですか?」

コンパイル時にそれらがわからないときはいつでも。つまり、Key-ValueコレクションMapが必要な場合は常にを使用する必要があります。コレクションが必要であることを示す良い指標は、コレクションに値を動的に追加および削除する場合、特にそれらの値が事前にわからない場合(たとえば、データベースから読み取られる場合、ユーザーが入力する場合など)です。

対照的に、コードの記述中にオブジェクトが持つプロパティとその数がわかっている場合、つまりオブジェクトの形状が静的である場合は、オブジェクトを使用する必要があります。@Felixが言っているように:レコードが必要なとき。これが必要な場合の良い指標は、フィールドのタイプが異なる場合、および角かっこ表記を使用する必要がない場合(または、プロパティ名のセットが限られていることを期待する場合)です。


1
または、別の観点から:for..ofプログラムレベル(例for..in)ではなくデータレベル(例)でオブジェクトのプロパティを反復処理する必要がある場合は常に、を使用しMapます。この応答のこの用語に関する詳細情報。

私はまた、コメントとして、いつでもあなたはあなたの鍵がされるタイプの種類を知っていないという事実が追加されますし、マップの使用、その後、キーのデータ型として文字列を期待していないstackoverflow.com/questions/32600157/...を
カーマインTambascia

26

ES2015Mapでは、プレーンオブジェクトを使用する理由は2つだけ残っていると思います。

  • オブジェクトタイプのプロパティを繰り返し処理する必要はありません。
  • または、そうしますが、プロパティの順序は重要ではなく、反復するときにプログラムとデータレベルを区別できます。

プロパティの順序が重要でないのはいつですか?

  • 値が1つだけで、それに明示的に関連付ける必要のある関数がいくつかある場合(Promiseたとえば、将来の値のプロキシです)およびthen/ catch
  • 「コンパイル時」に既知の静的なプロパティセットを持つ構造体/レコードのようなデータ構造がある場合(通常、構造体/レコードは反復可能ではありません)

他のすべての場合は、使用を検討できます Map、プロパティの順序を保持し、プログラム(Mapオブジェクトに割り当てられたすべてのプロパティ)をデータレベル(Mapそれ自体のすべてのエントリ)から分離するため、の。

の欠点は何ですか Map何ですか?

  • 簡潔なオブジェクトリテラル構文が失われます
  • JSON.stringyfyのカスタム置換が必要です
  • とにかく静的データ構造でより便利な破壊を失います

この行は私にとって非常に懸念されています。「純粋なハッシュマップのようなオブジェクトよりもおそらく遅い」パフォーマンスが向上したため、すべてのオブジェクトをマップに置き換えることを考えました。しかし、あなたはそれが遅いと言います...
mesqueeb 2018

1
あなたが正しい。Map純粋にハッシュに基づいているため、おそらく高速Objectですが、少し複雑です。ありがとう!

11

キーが実行時まで不明であり、すべてのキーが同じタイプであり、すべての値が同じタイプである場合は、オブジェクト上でマップを使用します。

なぜ誰かが明らかに間違った何かを書くのか私にはわかりません。私が言わなければならないのは、最近、人々はMDNでますます間違ったコンテンツや疑わしいコンテンツを見つけているということです。

その文の何も正しくありません。マップを使用する主な理由は、オブジェクト値のキーが必要な場合です。値が同じタイプでなければならないという考えはばかげています-もちろんそうかもしれませんが。キーが不明な場合は、実行時までオブジェクトを使用すべきではないという考えも同様にばかげています。


1
私はその考えについて何がそんなに馬鹿げているのか分かりませんか?コレクションが必要な場合、通常は厳密に型指定されます(もちろん例外がある場合もあります)。また、コレクションにオブジェクトを使用しないこと(Map利用可能な場合)は良いアドバイスだと思います。
ベルギ2015

そのため、コレクションは通常、厳密に型指定されているため、厳密に型指定されたものはコレクションである必要があると言うこととは論理的に異なります。

1
ええ、少し奇妙だと思いますが、アイデアは問題ありません。「キーは実行時までわからない」と思っていたのではないでしょうか。より良いフレージングのためのアイデアはありますか?
ベルギ2015

1
同意しました。MDNには非常に優れたドキュメントがありますが、APIドキュメントのドキュメントに固執し、プログラミングのアドバイスを提供しようとしないでください。
AlexG 2017年

5

違いの一つMapObjectされます。

Map複雑なデータ型をキーとして使用できます。このような:

const fn = function() {}
const m = new Map([[document.body, 'stackoverflow'], [fn, 'redis']]);

m.get(document.body) // 'stackoverflow'
m.get(fn) //'redis'

注意:複雑なデータ型の場合、値を取得する場合は、キーと同じ参照を渡す必要があります。

Object、キーとして単純なデータ型(numberstring)のみを受け入れます。

const a = {};
a[document.body] = 'stackoverflow';

console.log(a) //{[object HTMLBodyElement]: "stackoverflow"}

2

この質問は重複しています しかし、それが閉じられるまで、ここにそこから私の答えがあります:

他の答えに加えて、マップはオブジェクトよりも扱いにくく、操作が冗長であることがわかりました。

obj[key] += x
// vs.
map.set(map.get(key) + x)

これは重要です。コードが短いほど、読みやすく、表現力が高く、プログラマーの頭の中にとどまることができるからです。

別の側面:set()は値ではなくマップを返すため、割り当てを連鎖させることはできません。

foo = obj[key] = x;  // Does what you expect
foo = map.set(key, x)  // foo !== x; foo === map

マップのデバッグもより面倒です。以下では、実際にマップにどのキーがあるかを確認することはできません。そのためにはコードを書く必要があります。

マップイテレータを評価して頑張ってください

オブジェクトは任意のIDEで評価できます。

オブジェクトを評価するWebStorm


6
これは、質問に答えるしません「オブジェクトの上に地図を使用しての適用例である何を?全然」
Bergi

6
回答をクロスポストしないでください。いいえ、質問は重複していません。
ベルギ2017年

1

ObjectsはMap、キーを値に設定し、それらの値を取得し、キーを削除し、キーに何かが格納されているかどうかを検出できるという点でsに似ています。このため(そして組み込みの代替手段がなかったため)、ObjectsはMap歴史的にsとして使用されてきました。ただし、Map特定の場合に使用を推奨する重要な違いがあります。

  • のキーObjectStringsとSymbolsですがMap、関数、オブジェクト、プリミティブなど、の任意の値にすることができます。
  • のキーMapは順序付けられていますが、オブジェクトに追加されたキーは順序付けられていません。したがって、Mapオブジェクトを反復処理すると、オブジェクトは挿入順にキーを返します。
  • プロパティを使用してMap簡単にサイズを取得できますが、内のsizeプロパティの数はObject手動で決定する必要があります。
  • AMapは反復可能であるため、直接反復できますが、aを反復処理するにObjectは、何らかの方法でキーを取得し、それらを反復処理する必要があります。
  • Objectプロトタイプを持っているので、注意しないなら、あなたの鍵と衝突する可能性がマップ内のデフォルトのキーがあります。ES5map = Object.create(null)以降、これはを使用してバイパスできますが、これはめったに行われません。
  • Mapキーペアの頻繁な追加と削除を伴うシナリオでは、Aのパフォーマンスが向上する可能性があります。

MDN

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.