web-dev-qa-db-ja.com

ES6のマップとオブジェクト、使用するタイミング

参照: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));
79
Matthew Harwood

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

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

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

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

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

47
Bergi

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

プロパティの順序が重要でない場合

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

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

Mapの欠点は何ですか?

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

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

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

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

10
user663031

MapObjectの違いの1つは次のとおりです。

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

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

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

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

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

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

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

この質問はの複製ですが、終了するまで そこからの私の答え です。

他の答えに加えて、Mapsはオブジェクトよりも扱いにくく、操作が難しいことがわかりました。

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

マップのデバッグも苦痛です。以下では、マップ内のキーを実際に見ることはできません。そのためにはコードを書く必要があります。

Good luck evaluating a Map Iterator

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

WebStorm evaluating an object

2
Dan Dascalescu

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

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

[〜#〜] mdn [〜#〜]

0
John Kennedy