JavaScript にはすでに Object があるのに、なぜ Map が必要なのでしょうか?

JavaScript にはすでに Object があるのに、なぜ Map が必要なのでしょうか?

1. オブジェクトをマップとして扱わない

1. 未定義のプロパティはプロトタイプチェーンを通じてアクセスできる

現在のシナリオを想定すると、Web サイトを開発するときに、日本語、中国語、韓国語の 3 つの言語を提供する必要があります。これらを管理するための辞書を定義できます。

定数辞書 = {
    'ja': {
        「雇える忍者」: 「雇える忍者」,
    },
    'zh': {
        「雇える忍者」: 「雇える忍者」,
    },
    'コ': {
        「雇える忍者」: 「雇う忍者」,
    }
}

console.log(dictionary.ja['Ninjas for hire']) // 雇える忍者console.log(dictionary.zh['Ninjas for hire']) // 雇える忍者console.log(dictionary.ko['Ninjas for hire']) // 雇える忍者console.log(dictionary.ko['Ninjas for hire']) // 雇える忍者

このようにして、さまざまな言語の辞書を管理します。ただし、 constroctorプロパティにアクセスしようとすると問題が発生します。

console.log(dictionary.ko['constructor']) // ƒ Object() { [ネイティブコード] }

存在しないプロパティの場合、 undefined返されることが予想されますが、プロトタイプ チェーンを通じて undefined プロパティにアクセスします。プロトタイプ オブジェクトのconstructorプロパティはコンストラクターを指します。

ここでの解決策の1つは、プロトタイプをnullに設定することです。

Object.setPrototypeOf(dictionary.ko, null)
console.log(dictionary.ko['constructor']) // 未定義

2. オブジェクトのキーは文字列のみにすることができます

オブジェクトのkey htmlノードにマップする必要があるとします。次のコードを記述します。

/* HTML 部分 <div id="firstElement"></div>
<div id="secondElement"></div>
*/

定数 firstElement = document.getElementById('firstElement')
定数 secondElement = document.getElementById('secondElement')

定数マップ = {}

map[最初の要素] = {
    データ: 'firstElement'
}
map[2番目の要素] = {
    データ: 'secondElement'
}

console.log(map[firstElement].data) // 2番目の要素
console.log(map[secondElement].data) // 2番目の要素

オブジェクト内のキーは文字列型のみであるため、最初の要素のデータは上書きされます。文字列型を使用しない場合は、暗黙的にtoString () 関数を呼び出して変換します。したがって、両方の HTML 要素は文字列[object HTMLDivElement]に変換されます。

オブジェクト キーはSymbolにすることもできますが、 Symbolキーはfor..inトラバーサル、 Object.keys() 、およびJSON.stringify()によるシリアル化中には無視されます。

2. マップの使用

1. 一般的なマップ操作

Map任意のJavaScriptデータ型をキーとして使用できます

関数 People(名前) {
    this.name = 名前
}
const zhangsan = new People('zhangsan')
const xiaoming = 新しい People('xiaoming')
const lihua = 新しい People('lihua')
// マップを作成する
定数マップ = 新しいマップ()
// マップを作成し、それを初期化して、2次元のキーと値の配列をマップオブジェクトに変換します。const map1 = new Map([
    ['キー1', '値1'],
    ['キー2', '値2'],
])
// Map を 2 次元配列に変換 console.log(Array.from(map1)) // [ [ 'key1', 'val1' ], [ 'key2', 'val2' ] ]
// キーと値のマッピング関係を設定する map.set(zhangsan, { region: 'HB' })
map.set(xiaoming, { 地域: 'HN' })
// キーに応じて対応する値を取得します console.log(map.get(zhangsan)) // { region: 'HB' }
console.log(map.get(xiaoming)) // { リージョン: 'HN' }
// 存在しないキーを取得し、未定義を取得します
console.log(map.get(lihua)) // 未定義
// 指定されたキーが存在するかどうかを判断するには、has 関数を使用します。console.log(map.has(lihua)) // false
console.log(map.has(xiaoming)) // 真
//map はマッピングの数を保存しますconsole.log(map.size) // 2
// 削除キーを削除する
map.delete(シャオミン)
console.log(map.has(xiaoming)) // false
コンソール.log(マップ.サイズ) // 1
// clear はマップをクリアします
マップをクリアする()
コンソール.log(マップ.サイズ) // 0

2. マップを移動する

マップは、トラバース順序が挿入順序と一致することを保証できる

const zhangsan = { 名前: 'zhangsan' }
const xiaoming = { 名前: 'xiaoming' }
定数マップ = 新しいマップ()
map.set(張山、{地域: 'HB' })
map.set(xiaoming, { 地域: 'HN' })
// 各キーと値のペアは [key, value] の配列を返します for (let item of map) { // = for (let item of map.entries()) {
    コンソール.log(アイテム)
    // [ { 名前: 'zhangsan' }, { 地域: 'HB' } ]
    // [ { 名前: 'xiaoming' }, { 地域: 'HN' } ]
}
// キーをトラバースする
(map.keys() のキーを取得) {
    console.log(キー)
    // { 名前: 'zhangsan' }
    // { 名前: 'xiaoming' }
}
// トラバース値
for (let key of map.values()) {
    console.log(キー)
    // { リージョン: 'HB' }
    // { 地域: 'HN' }
}
// forEach() メソッドを使用して Map を反復処理します
map.forEach(関数(値、キー) {
    console.log(キー、値)
    // { 名前: 'zhangsan' } { 地域: 'HB' }
    // { 名前: 'xiaoming' } { 地域: 'HN' }
})

3. マップ内のキーの等価性を判断する

Map内部的にSameValueZero比較演算を使用します。

SameValueSameValueZeroについて

SameValue ( Object.is() ) は、NaN と +0、-0 を厳密な等価性 (===) とは異なる方法で処理します。

Object.is(NaN, NaN) // 真
Object.is(0, -0) // 偽

SameValueZeroSameValueの主な違いは、0 が -0 に等しいかどうかです。

マップを設定します(NaN, 0)
マップを設定します(0, 0)
console.log(map.has(NaN)) // 真
console.log(map.has(-0)) // 真

4. マップをコピーまたは結合する

マップは配列のようにコピーできる

オリジナル = 新しいマップ([
    [1, {}]
])
let clone = new Map(original) // マップを複製する

console.log(clone.get(1)); // {}
console.log(オリジナル === クローン) // false
console.log(original.get(1) === clone.get(1)) // 真

複数のマップを結合する

まず、新しいMap([
    [1, '1'],
    [2, '2'],
    [3, '3'],
]);
2番目 = 新しいMap([
    [1, 'uno'],
    [2, 'する']
]);
// 2 つの Map オブジェクトをマージするときに、重複するキー値がある場合は、後者が前者を上書きします。
// スプレッド演算子は基本的に Map オブジェクトを配列に変換します。
マージされたMapを新しいMap([...first, ...second])にします。

console.log(merged.get(1)); // 未
console.log(merged.get(2)); // 実行
console.log(merged.get(3)); // 3つ

5. マップのシリアル化

Mapシリアル化できません。JSON.stringify JSON.stringify使用して Map の JSON を取得しようとすると、"{}" のみが取得されます。

マップのキーは任意のデータ型にすることができ、JSON ではキーとして文字列のみが許可されるため、通常、マップを JSON に変換することはできません。

ただし、次の方法で Map をシリアル化することができます。

// Map(1) を初期化します {"key1" => "val1"}
const originMap = 新しい Map([['key1', 'val1']])
// "[[\"key1\",\"val1\"]]" をシリアル化します
const mapStr = JSON.stringify(Array.from(originMap.entries())) 
// デシリアライズ Map(1) {"key1" => "val1"}
const cloneMap = 新しい Map(JSON.parse(mapStr))

3. マップとオブジェクトのパフォーマンスの違い

メモリ使用量

状況はブラウザによって異なりますが、メモリ量が固定されている場合、 Map Objectよりも約 50% 多くのキー/値のペアを保存できます。

挿入パフォーマンス

マップは若干高速なので、多数Map操作が関係する場合に推奨されます。

検索速度

パフォーマンスの違いは最小限ですが、オブジェクトに含まれるキーと値のペアの数が少ない場合は、 Object方が高速になることがあります。 Objectが配列として使用される場合、ブラウザは最適化を実行します。多数の検索操作が関係する場合は、Object の方が適しています。

削除パフォーマンス

コードに削除操作が多数含まれる場合は、 Mapを選択することをお勧めします。

これで、 JavaScriptObjectがすでにあるのに Map が必要な理由についての記事は終わりです。より関連性の高いJavaScript Mapコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • JavaScript にはすでに Object があるのに、なぜ Map が必要なのでしょうか?
  • JAVA における JSONObject オブジェクトと Map オブジェクト間の変換
  • JavaScript における Object、map、weakmap の違いの分析
  • Java で JSONObject を HashMap に変換する (メソッド + メイン メソッド呼び出しの例)
  • Json 文字列とオブジェクト、リスト、マップの変換ツール クラス
  • Json デシリアライゼーション ObjectMapper のサンプル分析 (デシリアライゼーション メソッドのカスタム実装)
  • ObjectMapper クラスを使用して Java で Json と Bean 間の変換を実装する例
  • MapとObject間、MapとJson間の変換を実装するJavaコード
  • JavaScript で配列とオブジェクトを使用してマップを実装する方法

<<:  MySQL 8.0 の降順インデックス

>>:  Tomcat でのサーブレットの作成と実装に関する深い理解

推薦する

Fabric.js は DIY ポストカード機能を実装します

この記事では、DIYポストカード機能を実現するためのfabricjsの具体的なコードを参考までに共有...

MySQLにおけるトランザクションの永続性実装原理の詳細な説明

序文データベース トランザクションに関して言えば、トランザクションの ACID 特性、分離レベル、解...

MySQLテーブルにタイムスタンプを追加するいくつかの方法

シナリオ:テーブル内のデータは、同期ツールを使用して他のデータベースと同期する必要があり、増分同期に...

Windows で MySQL インストーラーを使用して MySQL サービスをインストールするチュートリアル図

MYSQL は、MYSQL サービスやその他のコンポーネントをインストールするためのインストーラ方式...

mysql と oracle のデフォルトのトランザクション分離レベルの説明

1. トランザクション特性(ACID) (1)原子性トランザクションに関係するプログラムによって実行...

React Router 5.1.0 はページジャンプナビゲーションを実装するために useHistory を使用します

目次1. withRouterコンポーネントを使用する2. ルートタグを使用するReactRoute...

JavaScriptは入力ボックスコンポーネントを実装します

この記事では、入力ボックスコンポーネントを手動で実装するための具体的なコードを参考までに紹介します。...

Vue3 のリアクティブ関数 toRef 関数 ref 関数の紹介

目次リアクティブ機能使用法: toRef 関数 (理解するだけ)使用法: ref関数レスポンシブデー...

MySQL データ型 DECIMAL の使用方法の詳細な説明

MySQL DECIMALデータ型は、データベースに正確な数値を保存するために使用されます。会計シス...

MySQLの起動失敗の解決策

MySQLの起動失敗の解決策MySQLを起動できませんmysqlを停止した後、いくつかの操作(ホスト...

MySQL ルートパスワードをリセットする方法

目次1. ルートパスワードを忘れてしまい、データベースにアクセスできない: DBA にとって、スーパ...

Kubernetes YAMLファイルの使用

目次01 YAMLファイルの概要YAML---キー値型YAML---リスト型02 K8Sにおけるマス...

MySQLインデックスの使用に関するヒントと注意事項

1. インデックスの役割一般的なアプリケーション システムでは、読み取りと書き込みの比率は約 10:...

Net Core実装プロセス分析のDoc​​kerインストールと展開

1. Dockerのインストールと設定 #CentOS をインストールし、Docker パッケージを...

HTML タグの表示モード (ブロックレベル タグ、インライン タグ、インライン ブロック タグ) に関する簡単な説明

今日の講義では、HTML におけるタグの表示モードについてお話ししましたが、これはブロックレベルタグ...