表示されているページは、編集用 バージョンの MDN Web Docsです

MDN Web Docs のユーザーとして表示: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map

Map オブジェクトはキーと値のペアを保持し、キーが最初に挿入された順序を覚えています。キーや値には任意の値 (オブジェクトとプリミティブ値)を使用することができます。

解説

Map オブジェクトは、その要素について挿入順で反復処理を行うことができます。 for...of ループは各反復で [キー, ] の配列を返します。

キーの等価性

  • キーの等価性は sameValueZero アルゴリズムに基づきます。
  • NaNNaN と同じとみなされ (NaN !== NaN であっても)、他の値はすべて === 演算子の意味に従って等価性が考慮されます。
  • 現在の ECMAScript 仕様書では、 -0+0 は等しいと考えられています。但し、以前の草稿ではそのようになっていませんでした。詳細は "Value equality for -0 and 0"ブラウザーの互換性一覧で確認してください。

Object と Map の比較

ObjectMap は似ています。 — どちらもキーを値に設定したり、それらの値を受け取ったり、キーを削除したり、キーに何かが格納されているかどうかを判定したりすることができます。この意味で (そして他の内蔵オブジェクトがなかったため)、従来 ObjectMap として使われてきました。

しかし、いくつかの場面で Map の方が勝るような重要な違いがあります。

Map Object
思いがけないキー Map は既定では何もキーを持っていません。明示的に設定したものだけを含みます。

Object にはプロトタイプがあります。よって既定のキーを含んでいるので、注意しないと自分のキーと衝突する可能性があります。

注: ES5 では、 Object.create(null) を使用すると回避できますが、これはめったに行われていません。

キーの型 Map のキーはあらゆる値がなることができます (関数、オブジェクト、あらゆるプリミティブなど)。 Object のキーは String または Symbol でなければなりません。
キーの順序

Map のキーは、単純で直感的な方法で順序付けられます。すなわち、反復処理を行うと、 Map オブジェクトは挿入順でキーを返します。

通常の Object のキーは現在では順序付けされていますが、以前はそうではなかったので、順序は複雑です。結果として、プロパティの順序に頼らない方が良いでしょう。

この順序は ECMAScript 2015 で初めて自身のプロパティに対してのみ定義されましたが、 ECMAScript 2020 では継承されたプロパティに対しても同様に順序が定義されています。 OrdinaryOwnPropertyKeysEnumerateObjectProperties の抽象指定操作を参照してください。しかし、オブジェクトのプロパティがすべて反復処理される単一の単一のメカニズムはないことに注意してください。 (for-in は列挙可能な文字列キーのプロパティのみを含む、 Object.keys は自分自身の列挙可能な文字列キーのプロパティのみを含む、 Object.getOwnPropertyNames は列挙不可能な場合でも自分自身の文字列キーのプロパティを含む、 Object.getOwnPropertySymbols は、 Symbol キーを持つプロパティに対しても同じことを行う、など。)

大きさ

Map の中の項目数は、 size プロパティで簡単に得ることができます。 property. Object の中の項目数は、手動で数える必要があります。
反復処理 Mapiterable ですので、直接反復処理を行うことができます。 Object では反復処理を行うのに、いくつかの形でキーの一覧を取得して、そのうえで反復処理を行う必要があります。
性能

キーと値の組を頻繁に追加したり削除したりすることが求められるシナリオでは、性能がより良くなります。

キーと値の組を頻繁に追加したり削除したりすることに最適化されていません。

オブジェクトプロパティの設定

Map オブジェクトに対してオブジェクトプロパティを設定すると正しく動作しますが、混乱を催すことが考えられます。

たとえば、次の例は一応動作するように見えます。

let wrongMap = new Map()
wrongMap['bla'] = 'blaa'
wrongMap['bla2'] = 'blaaa2'

console.log(wrongMap)  // Map { bla: 'blaa', bla2: 'blaaa2' }

しかし、このようにプロパティを設定すると、 Map データ構造に符合しません。一般的なオブジェクトの機能を使用します。 'bla' の値はクエリを行うための Map に格納されません。データにその他の操作を行うと失敗します。

wrongMap.has('bla')    // false
wrongMap.delete('bla') // false
console.log(wrongMap)  // Map { bla: 'blaa', bla2: 'blaaa2' }

Map にデータを格納する正しい方法は、 set(key, value) メソッドを使用する方法です。

let contacts = new Map()
contacts.set('Jessie', {phone: "213-555-1234", address: "123 N 1st Ave"})
contacts.has('Jessie') // true
contacts.get('Hilary') // undefined
contacts.set('Hilary', {phone: "617-555-4321", address: "321 S 2nd St"})
contacts.get('Jessie') // {phone: "213-555-1234", address: "123 N 1st Ave"}
contacts.delete('Raymond') // false
contacts.delete('Jessie') // true
console.log(contacts.size) // 1

コンストラクター

Map()
新しい Map オブジェクトを生成します。

静的プロパティ

get Map[@@species]
派生クラスを生成するためのコンストラクター関数です。

インスタンスプロパティ

Map.prototype.size
Map オブジェクトの中のキーと値の組の数を返します。

インスタンスメソッド

Map.prototype.clear()
Mapオブジェクトからすべてのキーと値の組を削除します。
Map.prototype.delete(key)
Map オブジェクトに要素が存在し、削除された場合は true を返します、要素が存在しなければ false を返します。その後では Map.prototype.has(key)false を返すようになります。
Map.prototype.get(key)
key で指定されたキーに結び付けられた値を返します。存在しない場合は undefined を返します。
Map.prototype.has(key)
key で指定されたキーに結び付けられた要素が Map オブジェクト内に存在するかどうかを示す boolean を返します。
Map.prototype.set(key, value)
Map オブジェクト内の key で指定されたキーの値を value に設定します。その Map オブジェクトを返します。

反復処理メソッド

Map.prototype[@@iterator]()
新しいイテレーターオブジェクトを返し、これには Mapオブジェクト内の各要素の [key, value] の配列が挿入順で含まれます。
Map.prototype.keys()
新しいイテレーターオブジェクトを返し、これには Mapオブジェクト内の各要素のキーが挿入順で含まれます。
Map.prototype.values()
新しいイテレーターオブジェクトを返し、これには Mapオブジェクト内の各要素のが挿入順で含まれます。
Map.prototype.entries()
Mapオブジェクト内の要素に対して挿入順にすべての要素の [key, value] の配列を含む、新しいイテレーターオブジェクトを返します。
Map.prototype.forEach(callbackFn[, thisArg])
callbackFn を、 Map オブジェクトに存在するそれぞれのキーと値の組に対して1回ずつ、挿入順に呼び出します。 thisArg 引数が forEach に与えられた場合は、それぞれのコールバックでこれを this の値として使用します。

Map オブジェクトの使用

let myMap = new Map()

let keyString = '文字列'
let keyObj    = {}
let keyFunc   = function() {}

// 値を設定する
myMap.set(keyString, "'文字列' と結び付けられた値")
myMap.set(keyObj, "keyObj と結び付けられた値")
myMap.set(keyFunc, "keyFunc と結び付けられた値")

myMap.size              // 3

// 値を取得する
myMap.get(keyString)    // "'文字列' と結び付けられた値"
myMap.get(keyObj)       // "keyObj と結び付けられた値"
myMap.get(keyFunc)      // "keyFunc と結び付けられた値"

myMap.get('文字列')     // "'文字列' と結び付けられた値"
                        // keyString === '文字列' であるため
myMap.get({})           // undefined, keyObj !== {} であるため
myMap.get(function() {}) // undefined, keyFunc !== function () {} であるため

NaN を Map のキーとして使用

NaN もまたキーとして使うことができます。すべての NaN は自身と等しくない (NaN !== NaN は真) にもかかわらず、以下の例は動作します。これは NaN が互いに区別できないためです。

let myMap = new Map()
myMap.set(NaN, 'not a number')

myMap.get(NaN) 
// "not a number"

let otherNaN = Number('foo')
myMap.get(otherNaN) 
// "not a number"

for..of を使用した Map の反復処理

Map は for..of ループを使用して反復処理を行うことができます。

let myMap = new Map()
myMap.set(0, 'zero')
myMap.set(1, 'one')

for (let [key, value] of myMap) {
  console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one

for (let key of myMap.keys()) {
  console.log(key)
}
// 0
// 1

for (let value of myMap.values()) {
  console.log(value)
}
// zero
// one

for (let [key, value] of myMap.entries()) {
  console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one

forEach() で Map を反復処理

Map は forEach() メソッドを使用して反復できます。

myMap.forEach(function(value, key) {
  console.log(key + ' = ' + value)
})
// 0 = zero
// 1 = one

Array オブジェクトとの関係

let kvArray = [["キー1", "値1"], ["キー2", "値2"]];

// 通常の Map コンストラクターを使って、キー・値の 2 次元配列をマップに変換する
let myMap = new Map(kvArray)

myMap.get("キー1") // "値1" を返す

// 展開演算子を使って、マップをキー・値の 2 次元配列に変換する
console.log(Array.from(myMap)) // kvArray とまったく同じ Array を表示する

// あるいは展開演算子をキーまたは値のイテレーターに使って、キーまたは値のみの配列を得る
console.log([...myMap])

// または keys() や values() のイテレーターを使用して配列に変換する
console.log(Array.from(myMap.keys())) // ["key1", "key2"] が出力される

Map の複製と混合

Array と同様に、 Map は複製することができます。

let original = new Map([
  [1, 'one']
])

let clone = new Map(original)

console.log(clone.get(1))       // one
console.log(original === clone) // false (useful for shallow comparison)

重要: データ自身は複製されないことに注意しておいてください。

Map はキーの固有性を保持しながら混合可能です。

let first = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
])

let second = new Map([
  [1, 'uno'],
  [2, 'dos']
])

// 2つのマップを混合します。重複するキーは後勝ちになります。
// スプレッド演算子は基本的に Map を Array に変換します。
let merged = new Map([...first, ...second])

console.log(merged.get(1)) // uno
console.log(merged.get(2)) // dos
console.log(merged.get(3)) // three

Map は Array と混合することもできます。

let first = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
])

let second = new Map([
  [1, 'uno'],
  [2, 'dos']
])

// マップと配列を混合します。重複するキーは後勝ちになります。
let merged = new Map([...first, ...second, [1, 'eins']])

console.log(merged.get(1)) // eins
console.log(merged.get(2)) // dos
console.log(merged.get(3)) // three

仕様書

仕様書
ECMAScript (ECMA-262)
Map の定義

ブラウザーの互換性

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung InternetNode.js
MapChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 13IE 完全対応 11Opera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 14Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
完全対応 0.12
完全対応 0.10
無効
無効 From version 0.10: this feature is behind the --harmony runtime flag.
Map() constructorChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 13IE 完全対応 11Opera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 14Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
完全対応 0.12
完全対応 0.10
無効
無効 From version 0.10: this feature is behind the --harmony runtime flag.
clearChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 19IE 完全対応 11Opera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 19Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
deleteChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 13IE 完全対応 11Opera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 14Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
完全対応 0.12
完全対応 0.10
無効
無効 From version 0.10: this feature is behind the --harmony runtime flag.
entriesChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 20IE 未対応 なしOpera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 20Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
forEachChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 25IE 完全対応 11Opera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 25Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
getChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 13IE 完全対応 11Opera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 14Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
完全対応 0.12
完全対応 0.10
無効
無効 From version 0.10: this feature is behind the --harmony runtime flag.
hasChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 13IE 完全対応 11Opera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 14Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
完全対応 0.12
完全対応 0.10
無効
無効 From version 0.10: this feature is behind the --harmony runtime flag.
Key equality for -0 and 0Chrome 完全対応 38Edge 完全対応 12Firefox 完全対応 29IE 未対応 なしOpera 完全対応 25Safari 完全対応 9WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 29Opera Android 完全対応 25Safari iOS 完全対応 9Samsung Internet Android 完全対応 3.0nodejs 完全対応 4.0.0
keysChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 20IE 未対応 なしOpera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 20Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
setChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 13IE 部分対応 11
補足
部分対応 11
補足
補足 Returns 'undefined' instead of the 'Map' object.
Opera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 14Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
完全対応 0.12
完全対応 0.10
無効
無効 From version 0.10: this feature is behind the --harmony runtime flag.
sizeChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 19
補足
完全対応 19
補足
補足 From Firefox 13 to Firefox 18, the size property was implemented as a Map.prototype.size() method, this has been changed to a property in later versions conform to the ECMAScript 2015 specification.
IE 完全対応 11Opera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 19
補足
完全対応 19
補足
補足 From Firefox 13 to Firefox 18, the size property was implemented as a Map.prototype.size() method, this has been changed to a property in later versions conform to the ECMAScript 2015 specification.
Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
valuesChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 20IE 未対応 なしOpera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 20Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 3.0nodejs 完全対応 0.12
@@iteratorChrome 完全対応 43Edge 完全対応 12Firefox 完全対応 36
完全対応 36
未対応 27 — 36
補足 代替名
補足 A placeholder property named @@iterator is used.
代替名 非標準の名前 @@iterator を使用しています。
未対応 17 — 27
補足 代替名
補足 A placeholder property named iterator is used.
代替名 非標準の名前 iterator を使用しています。
IE 未対応 なしOpera 完全対応 30Safari 完全対応 10WebView Android 完全対応 43Chrome Android 完全対応 43Firefox Android 完全対応 36
完全対応 36
未対応 27 — 36
補足 代替名
補足 A placeholder property named @@iterator is used.
代替名 非標準の名前 @@iterator を使用しています。
未対応 17 — 27
補足 代替名
補足 A placeholder property named iterator is used.
代替名 非標準の名前 iterator を使用しています。
Opera Android 完全対応 30Safari iOS 完全対応 10Samsung Internet Android 完全対応 4.0nodejs 完全対応 0.12
@@speciesChrome 完全対応 51Edge 完全対応 13Firefox 完全対応 41IE 未対応 なしOpera 完全対応 38Safari 完全対応 10WebView Android 完全対応 51Chrome Android 完全対応 51Firefox Android 完全対応 41Opera Android 完全対応 41Safari iOS 完全対応 10Samsung Internet Android 完全対応 5.0nodejs 完全対応 6.5.0
完全対応 6.5.0
完全対応 6.0.0
無効
無効 From version 6.0.0: this feature is behind the --harmony runtime flag.
@@toStringTagChrome 完全対応 44Edge 完全対応 79Firefox 完全対応 51IE 未対応 なしOpera 未対応 なしSafari 完全対応 9.1WebView Android 完全対応 44Chrome Android 完全対応 44Firefox Android 完全対応 51Opera Android 未対応 なしSafari iOS 完全対応 9.3Samsung Internet Android 完全対応 4.0nodejs 完全対応 6.0.0

凡例

完全対応  
完全対応
部分対応  
部分対応
未対応  
未対応
実装ノートを参照してください。
実装ノートを参照してください。
ユーザーが明示的にこの機能を有効にしなければなりません。
ユーザーが明示的にこの機能を有効にしなければなりません。
非標準の名前を使用しています。
非標準の名前を使用しています。

関連情報

ドキュメントのタグと貢献者

最終更新者: mfuji09,