Map

Это экспериментальная технология, часть предложения Harmony (ECMAScript 6).
Поскольку спецификация этой технологии ещё не стабилизировалась, проверьте таблицу совместимости её использования в различных браузерах. Также обратите внимание, что синтаксис и поведение экспериментальной технологии могут быть изменены в будущих версиях браузеров в соответствии с изменениями в спецификации.

Сводка

Объект Map является простым ассоциативным массивом. Любые типы (как объекты, так и примитивы) могут быть использованы в качестве ключа или значения.

Синтаксис

new Map([iterable])

Параметры

iterable
Может быть массивом или любым другим итерируемым объектом, элементы которого являются парами ключ-значение. Каждая пара ключ-значение будет добавлена во вновь созданный экземпляр Map.

Описание

Элементы объекта Map можно обойти в порядке их вставки при помощи цикла for..of, где на каждой итерации будет возвращаться массив [ключ, значение].

Сравнение ключей

Сравнение ключей основано на алгоритме "подобное значение": NaN равно NaN (несмотря на то, что NaN !== NaN); все другие значения рассматриваются равными исходя из семантики оператора строго равенства ===. В ранних версиях черновика ECMAScript 6 -0 и +0 считались разными (несмотря на то, что -0 === +0), это было изменено в последующих версиях и адаптировано в Gecko 29 (Firefox 29 / Thunderbird 29 / SeaMonkey 2.26) (ошибка 952870) и последней ночной сборке Chrome.

Сходство объектов и map

Объекты похожи на Map в том, что и те и другие позволяют задавать значения по ключам, получать эти значения, удалять ключи и проверять наличие ключа. В связи с этим, исторически объекты использовались как Map, однако, у них есть существенные отличия:

  • Объект имеет прототип, что означает наличие стандартных значений в ассоциативном массиве. Однако, это можно обойти при помощи выражения map = Object.create(null).
  • В объекте ключи должны быть строками, когда в Map они могут иметь любой тип.
  • Вы можете легко получить размер Map, в то время как в объекте необходимо самостоятельно его учитывать.

Используйте ассоциативный массив вместо объекта когда тип ключей не известен до момента исполнения, либо тип всех ключей и тип всех значений одинаковый.

Используйте объекты, когда используется логика взаимодействия с ним как с отдельным элементом.

Свойства

Map.length
Значение  свойства length всегда равно 1.
Map.prototype
Представляет прототип конструктора Map. Позволяет добавлять свойства всем объектам типа Map.

Экземпляры Map

Все экземпляры Map унаследованы от Map.prototype.

Свойства

Map.prototype.constructor
Returns the function that created an instance's prototype. This is the Map function by default.
Map.prototype.size
Returns the number of key/value pairs in the Map object.

Методы

Map.prototype.clear()
Removes all key/value pairs from the Map object.
Map.prototype.delete(key)
Removes any value associated to the key and returns the value that Map.prototype.has(key) would have previously returned. Map.prototype.has(key) will return false afterwards.
Map.prototype.entries()
Returns a new Iterator object that contains an array of [key, value] for each element in the Map object in insertion order.
Map.prototype.forEach(callbackFn[, thisArg])
Calls callbackFn once for each key-value pair present in the Map object, in insertion order. If a thisArg parameter is provided to forEach, it will be used as the this value for each callback.
Map.prototype.get(key)
Returns the value associated to the key, or undefined if there is none.
Map.prototype.has(key)
Returns a boolean asserting whether a value has been associated to the key in the Map object or not.
Map.prototype.keys()
Returns a new Iterator object that contains the keys for each element in the Map object in insertion order.
Map.prototype.set(key, value)
Sets the value for the key in the Map object. Returns the Map object.
Map.prototype.values()
Returns a new Iterator object that contains the values for each element in the Map object in insertion order.
Map.prototype[@@iterator]()
Returns a new Iterator object that contains an array of [key, value] for each element in the Map object in insertion order.

Примеры

Использование объекта Map

var myMap = new Map();

var keyObj = {},
    keyFunc = function () {},
    keyString = "a string";

// задание значений
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

myMap.size; // 3

// получение значений
myMap.get(keyString);    // "value associated with 'a string'"
myMap.get(keyObj);       // "value associated with keyObj"
myMap.get(keyFunc);      // "value associated with keyFunc"

myMap.get("a string");   // "value associated with 'a string'"
                         // потому что keyString === 'a string'
myMap.get({});           // undefined, потому что keyObj !== {}
myMap.get(function() {}) // undefined, потому что keyFunc !== function () {}

Использование NaN в качестве ключей Map

NaN может быть использован в качестве ключа. Несмотря на то, что NaN не равен самому себе (NaN !== NaN вернёт true), следующий пример работает, потому что NaN обрабатывается особым образом:

var myMap = new Map();
myMap.set(NaN, "not a number");

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

var otherNaN = Number("foo");
myMap.get(otherNaN); // "not a number"

Обход Map при помощи for..of

Ассоциативные массивы можно обойти при помощи цикла a for..of:

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  alert(key + " = " + value);
}
// Отобразит 2 предупреждения; первое "0 = zero" и второе "1 = one"

for (var key of myMap.keys()) {
  alert(key);
}
// Отобразит 2 предупреждения; первое "0" и второе "1"

for (var value of myMap.values()) {
  alert(value);
}
// Отобразит 2 предупреждения; первое "zero" и второе "one"

for (var [key, value] of myMap.entries()) {
  alert(key + " = " + value);
}
// Отобразит 2 предупреждения; первое "0 = zero" и второе "1 = one"

myMap.forEach(function(value, key, myMap) {
  alert(key + " = " + value);
})
// Отобразит 2 предупреждения; первое "0 = zero" и второе "1 = one"

Взаимоотношения с объектом Array

var kvArray = [["key1", "value1"], ["key2", "value2"]];

// Используйте конструктор Map для преобразования двумерных массивов в ассоциативные
var myMap = new Map(kvArray);

myMap.get("key1"); // вернёт "value1"

// Используйте переменный оператор для преобразования ассоциативного в двумерный массив
alert(uneval([...myMap])); // Отобразит тот же массив, что и kvArray

// Или используйте переменный оператор для ключей или значений итератора для получения 
// массива только ключей или значений
alert(uneval([...myMap.keys()])); // Отобразит ["key1", "key2"]

Спецификации

Спецификация Статус Комментарий
ECMAScript 2015 (6th Edition, ECMA-262)
Определение 'Map' в этой спецификации.
Стандарт Изначальное определение.

Совместимость с браузерами

Возможность Chrome Firefox (Gecko) Internet Explorer Opera Safari
Базовая поддержка

31 [1]
38

13 (13) 11 25 7.1
Аргумент конструктора: new Map(iterable) 38 13 (13) Нет 25 Нет
Итерируемость 38 17 (17) Нет 25 7.1
Map.clear() 31 [1]
38
19 (19) 11 25 7.1
Map.keys(), Map.values(), Map.entries() 37 [1]
38
20 (20) Нет 25 7.1
Map.forEach() 36 [1]
38
25 (25) 11 25 7.1
Равенство ключей -0 и 0 34 [1]
38
29 (29) Нет 25 Нет
Возможность Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Базовая поддержка Нет 31 [1]
38
13.0 (13) Нет Нет iOS 8
Аргумент конструктора: new Map(iterable) Нет 38 13.0 (13) Нет Нет Нет
Итерируемость Нет Нет 17.0 (17) Нет Нет iOS 8
Map.clear() Нет 31 [1]
38
19.0 (19) Нет Нет iOS 8
Map.keys(), Map.values(), Map.entries() Нет 37 [1]
38
20.0 (20) Нет Нет iOS 8
Map.forEach() Нет 36 [1]
38
25.0 (25) Нет Нет iOS 8
Равенство ключей -0 и 0 Нет 34 [1]
38
29.0 (29) Нет Нет Нет

[1] Функция доступна при настройке. В chrome://flags, активируйте “Enable Experimental JavaScript”.

Смотрите также

Метки документа и участники

 Внесли вклад в эту страницу: dtretyakov
 Обновлялась последний раз: dtretyakov,