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 でのサーブレットの作成と実装に関する深い理解

推薦する

html+vue+element-ui のスムーズさを 1 分で体験

テクノロジーファンHTMLウェブページ、知っておくべきYouyou が開発した vue フロントエン...

InnoDB テーブルの BLOB 列と TEXT 列のストレージ効率を最適化します。

まず、MySQL InnoDB エンジンのストレージ形式に関する重要なポイントをいくつか紹介します。...

HTML/XHTML における img 画像タグの基本的な使用法の詳細な説明

画像タグは、Web ページに画像を表示するために使用されます。 HTML/XHTML 画像 <...

CSS3 オーバーフロープロパティの説明

1. オーバーフローOverflow はオーバーフロー(コンテナ)です。コンテンツがコンテナを越える...

Vue における v-model を使用したクロスコンポーネントバインディングの基本的な実装方法

みなさんこんにちは。今日はv-modelを使って親子コンポーネントのバインディング効果を実現する方法...

vue + Electron でデスクトップ アプリケーションを作成するためのサンプル コード

1.vueパッケージングここでは、vueネイティブパッケージングコマンドを使用してvueプロジェクト...

Ubuntu環境でxdebugをコンパイルしてインストールする方法

この記事では、Ubuntu 環境で xdebug をコンパイルしてインストールする方法について説明し...

Dockerを使用してMySQLデータベースをインストールするDeepinの詳細な説明

まずMySQLソースをクエリするdocker 検索 mysql公式ウェブサイトにアクセスしてイメージ...

SQLシリアル番号取得コード例

この記事は主にSQLシリアル番号取得コード例を紹介します。記事ではサンプルコードを詳細に紹介しており...

Linux 負荷分散 LVS の詳細な理解

目次1. LVS 負荷分散2. 負荷分散LVSの基本紹介3. LVSアーキテクチャ3.1 ロードバラ...

Centos7.3は起動時に自動的に起動または指定されたコマンドを実行します

Centos7では、/etc/rc.d/rc.localファイルの権限が削減されており、実行権限があ...

MySQL の同時実行性の問題と解決策の分析

目次1. 背景2. テーブルロックによるクエリの遅延3. オンラインでテーブル構造を変更するとどのよ...

win2008R2 64 ビット システムでの mysql5.7.17 のインストールと構成の例

123WORDPRESS.COM では、さまざまな環境での MYSQL の他のバージョンのインストー...

Mysql5.7.14 Linux版のパスワードを忘れた場合の完璧な解決策

/etc/my.confファイルで、[mysqld]の下に次の行を追加します: skip-grant...

js配列のfind、some、filter、reduceの違いの詳細な説明

Array の filter、find、some、reduce メソッドの違いを区別し、使用シナリオ...