プレーンJavaScriptオブジェクトの代わりにマップを使用するのはいつですか?
プレーンなJavaScriptオブジェクト{key: 'value'}は構造化データを保持します。ただし、プレーンなJSオブジェクトには制限があります。
オブジェクトのキーとして使用できるのは文字列と記号のみです。オブジェクトのキーとして数値などの他のことを使用すると、それらのキーにアクセスしているときに、それらのキーが文字列に変換され、暗黙的に型の一貫性が失われます。const names = {1: 'one'、2: 'two'}; Object.keys(names); // ['1'、 '2']
JS識別子をオブジェクトのキー名(toString、コンストラクタなど)として書き込むことにより、プロトタイプから継承されたプロパティを誤って上書きする可能性があります。
別のオブジェクトをオブジェクトのキーとして使用することはできないため、そのオブジェクトを別のオブジェクトのキーとして書き込むことによってそのオブジェクトに追加情報を書き込むことはできず、その別のオブジェクトの値には追加情報が含まれます
オブジェクトはイテレータではありません
オブジェクトのサイズを直接決定することはできません
オブジェクトのこれらの制限はマップによって解決されますが、マップを置換ではなくオブジェクトの補足と見なす必要があります。基本的に、Mapは配列の配列ですが、配列の配列を引数として新しいキーワードでMapオブジェクトに渡す必要があります。そうでない場合、配列の配列に対してのみ、Mapの便利なプロパティとメソッドを使用できません。また、配列の配列内のキーと値のペアまたはマップはカンマでのみ区切る必要があり、プレーンオブジェクトのようにコロンは使用しないでください。
マップとオブジェクトのどちらを使用するかを決定するための3つのヒント:
実行時までキーが不明な場合は、オブジェクトのマップを使用します。ユーザー入力によって形成されたキーは、オブジェクトの継承されたプロパティをそれらのキーが上書きする場合、オブジェクトを使用するコードを無意識のうちに破壊する可能性があるため、マップはより安全です。すべてのキーが同じタイプであり、すべてのマップが同じタイプである場合にもマップを使用します。
プリミティブ値をキーとして保存する必要がある場合は、マップを使用します。
個々の要素を操作する必要がある場合は、オブジェクトを使用します。
マップを使用する利点は次のとおりです。
1.マップは任意のキータイプを受け入れ、キーのタイプを保持します。
オブジェクトのキーが文字列またはシンボルでない場合、JSはそれを暗黙的に文字列に変換します。逆に、Mapは任意のタイプのキー(文字列、数値、ブール値、記号など)を受け入れ、Mapは元のキータイプを保持します。ここでは、マップ内のキーとして数値を使用しますが、数値のままです。
const numbersMap= new Map();
numbersMap.set(1, 'one');
numbersMap.set(2, 'two');
const keysOfMap= [...numbersMap.keys()];
console.log(keysOfMap); // [1, 2]
マップ内では、オブジェクト全体をキーとして使用することもできます。無駄のないオブジェクトを操作できるようにオブジェクトに関する情報を保存したいので、オブジェクト自体の内部にこのデータを添付せずに、オブジェクト関連のデータを保存したい場合があります。それらの場合、オブジェクトをキーとして、オブジェクトの関連データを値として作成できるように、マップを使用する必要があります。
const foo= {name: foo};
const bar= {name: bar};
const kindOfMap= [[foo, 'Foo related data'], [bar, 'Bar related data']];
ただし、この方法の欠点は、配列全体をループして目的の値を取得する必要があるため、キーで値にアクセスする複雑さです。
function getBy Key(kindOfMap, key) {
for (const [k, v] of kindOfMap) {
if(key === k) {
return v;
}
}
return undefined;
}
getByKey(kindOfMap, foo); // 'Foo related data'
適切なマップを使用することで、値に直接アクセスできないというこの問題を解決できます。
const foo= {name: 'foo'};
const bar= {name: 'bar'};
const myMap= new Map();
myMap.set(foo, 'Foo related data');
myMap.set(bar, 'Bar related data');
console.log(myMap.get(foo)); // 'Foo related data'
WeakMapを使用してこれを行うこともできますが、const myMap = new WeakMap()と記述するだけです。MapとWeakMapの違いは、WeakMapはキー(ここではオブジェクト)のガベージコレクションを可能にするため、メモリリークを防ぎ、WeakMapはオブジェクトとしてのみキーを受け入れ、WeakMapはメソッドのセットを減らしました。
2.マップにはキー名に対する制限はありません。
プレーンなJSオブジェクトの場合、プロトタイプから継承したプロパティを誤って上書きする可能性があり、危険な場合があります。ここでは、actorオブジェクトのtoString()プロパティを上書きします。
const actor= {
name: 'Harrison Ford',
toString: 'Actor: Harrison Ford'
};
次に、fn isPlainObject()を定義して、指定された引数がプレーンオブジェクトであるかどうかを確認します。このfnはtoString()メソッドを使用してそれをチェックします。
function isPlainObject(value) {
return value.toString() === '[object Object]';
}
isPlainObject(actor); // TypeError : value.toString is not a function
// this is because inside actor object toString property is a string instead of inherited method from prototype
Mapはキー名に制限はなく、toString、コンストラクタなどのキー名を使用できます。ここで、actorMapオブジェクトにはtoStringという名前のプロパティがありますが、actorMapオブジェクトのプロトタイプから継承されたメソッドtoString()は完全に機能します。
const actorMap= new Map();
actorMap.set('name', 'Harrison Ford');
actorMap.set('toString', 'Actor: Harrison Ford');
function isMap(value) {
return value.toString() === '[object Map]';
}
console.log(isMap(actorMap)); // true
ユーザー入力がキーを作成する状況がある場合、それらのキーをプレーンオブジェクトではなくマップ内に取得する必要があります。これは、ユーザーがtoString、コンストラクタなどのカスタムフィールド名を選択する可能性があるためです。プレーンオブジェクトのそのようなキー名は、後でこのオブジェクトを使用するコードを破壊する可能性があります。したがって、正しい解決策は、ユーザーインターフェイスの状態をマップにバインドすることです。マップを解除する方法はありません。
const userCustomFieldsMap= new Map([['color', 'blue'], ['size', 'medium'], ['toString', 'A blue box']]);
3.マップは反復可能です:
プレーンオブジェクトのプロパティを反復処理するには、Object.entries()またはObject.keys()が必要です。Object.entries(plainObject)は、オブジェクトから抽出されたキーと値のペアの配列を返します。これらのキーと値を分解して、通常のキーと値の出力を取得できます。
const colorHex= {
'white': '#FFFFFF',
'black': '#000000'
}
for(const [color, hex] of Object.entries(colorHex)) {
console.log(color, hex);
}
//
'white' '#FFFFFF'
'black' '#000000'
マップは反復可能であるため、マップを反復してキーを分解するためにentries()メソッドを必要としないので、値の配列はマップ内で直接実行できます。各要素は、コンマで区切られたキーと値のペアの配列として存在します。 。
const colorHexMap= new Map();
colorHexMap.set('white', '#FFFFFF');
colorHexMap.set('black', '#000000');
for(const [color, hex] of colorHexMap) {
console.log(color, hex);
}
//'white' '#FFFFFF' 'black' '#000000'
また、map.keys()はキーのイテレータを返し、map.values()は値のイテレータを返します。
4.地図のサイズを簡単に知ることができます
プレーンオブジェクトのプロパティの数を直接決定することはできません。オブジェクトのキーを含む配列を返すObject.keys()のようなヘルパーfnが必要です。次に、lengthプロパティを使用して、キーの数またはプレーンオブジェクトのサイズを取得できます。
const exams= {'John Rambo': '80%', 'James Bond': '60%'};
const sizeOfObj= Object.keys(exams).length;
console.log(sizeOfObj); // 2
ただし、マップの場合、map.sizeプロパティを使用してマップのサイズに直接アクセスできます。
const examsMap= new Map([['John Rambo', '80%'], ['James Bond', '60%']]);
console.log(examsMap.size);