Map
Базовый уровень Широко доступно
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и в различных версиях браузеров. Она доступна во всех браузерах с июля 2015 года.
Объект Map хранит пары ключ-значение и запоминает исходный порядок вставки ключей. Любое значение (как объекты, так и примитивные значения) может быть использовано в качестве ключа или значения.
Попробуйте
const map = new Map();
map.set("a", 1);
map.set("b", 2);
map.set("c", 3);
console.log(map.get("a"));
// Expected output: 1
map.set("a", 97);
console.log(map.get("a"));
// Expected output: 97
console.log(map.size);
// Expected output: 3
map.delete("b");
console.log(map.size);
// Expected output: 2
Описание
Объекты Map представляют собой коллекции пар ключ-значение. Ключ в Map может встречаться только один раз; он уникален в коллекции Map. Объект Map итерируется по парам ключ-значение — цикл for...of возвращает массив из 2 элементов [key, value] для каждой итерации. Итерация происходит в порядке вставки, который соответствует порядку, в котором каждая пара ключ-значение была впервые вставлена в Map с помощью метода set() (то есть, когда вызывался set(), ключа с таким же значением еще не было в Map).
Спецификация требует, чтобы реализация Map «в среднем обеспечивала время доступа, которое является сублинейным относительно числа элементов в коллекции». Следовательно, она может быть представлена внутри как хеш-таблица (с поиском O(1)), дерево поиска (с поиском O(log(N))) или любая другая структура данных, при условии, что сложность лучше, чем O(N).
Равенство ключей
Равенство значений основано на алгоритме SameValueZero. (Раньше использовался SameValue, который рассматривал 0 и -0 как разные. Проверьте совместимость с браузерами.) Это означает, что NaN считается тем же, что и NaN (хотя NaN !== NaN), а все остальные значения считаются равными в соответствии с семантикой оператора ===. Кроме того, для ключей-объектов равенство основано на идентичности объекта. Они сравниваются по ссылке, а не по значению. Примеры см. в разделе Использование объекта Map.
Объекты (Objects) против Map
Object похож на Map—оба позволяют устанавливать ключи для значений, извлекать эти значения, удалять ключи и определять, хранится ли что-либо по ключу. По этой причине (и из-за отсутствия встроенных альтернатив) Object исторически использовался как Map.
Однако есть важные различия, которые делают Map предпочтительным в некоторых случаях:
| Map | Object | |
|---|---|---|
| Случайные ключи | Map по умолчанию не содержит никаких ключей. Он содержит только то, что явно в него помещено. | Объект Примечание: Это можно обойти, используя |
| Безопасность | Map безопасно использовать с предоставленными пользователем ключами и значениями. | Установка предоставленных пользователем пар ключ-значение в |
| Типы ключей | Ключи Map могут быть любым значением (включая функции, объекты или любой примитив). | Ключи Object должны быть либо String, либо Symbol. |
| Порядок ключей | Ключи в | Хотя ключи обычного Порядок был впервые определён только для собственных свойств в ECMAScript 2015; ECMAScript 2020 также определяет порядок для унаследованных свойств. Но обратите внимание, что ни один механизм не итерирует все свойства объекта; различные механизмы включают разные подмножества свойств. ( |
Размер | Количество элементов в Map легко получить из его свойства size. | Определение количества элементов в Object более сложно и менее эффективно. Обычный способ сделать это — использовать length массива, возвращаемого Object.keys(). |
| Итерация | Map является итерируемым объектом, поэтому его можно итерировать напрямую. | Примечание:
|
| Производительность | Работает лучше в сценариях, связанных с частым добавлением и удалением пар ключ-значение. | Не оптимизирован для частого добавления и удаления пар ключ-значение. |
| Сериализация и разбор | Нет встроенной поддержки сериализации или разбора. (Но вы можете создать свою собственную поддержку сериализации и разбора для | Встроенная поддержка сериализации из Встроенная поддержка разбора из JSON в |
Установка свойств объекта
Установка свойств объекта также работает для объектов Map и может вызвать значительное замешательство.
Таким образом, кажется, что это работает:
const 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).
const 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
Браузерные API, похожие на Map
Браузерные объекты, похожие на Map (или «maplike-объекты»), — это интерфейсы Web API, которые во многом ведут себя как Map.
Как и в Map, записи могут итерироваться в том же порядке, в котором они были добавлены в объект. Объекты, похожие на Map, и Map также имеют свойства и методы с одинаковыми именами и поведением. Однако, в отличие от Map, они допускают только определённые предопределённые типы для ключей и значений каждой записи.
Разрешённые типы устанавливаются в определении IDL спецификации. Например, RTCStatsReport — это объект, похожий на Map, который должен использовать строки для ключей и объекты для значений. Это определено в IDL спецификации ниже:
interface RTCStatsReport {
readonly maplike<DOMString, object>;
};
Объекты, похожие на Map, бывают либо доступными только для чтения (read-only), либо доступными для чтения и записи (read-writable) (см. ключевое слово readonly в IDL выше).
- Объекты, похожие на
Map, доступные только для чтения, имеют свойствоsizeи методы:entries(),forEach(),get(),has(),keys(),values(), и[Symbol.iterator](). - Объекты, похожие на
Map, доступные для записи, дополнительно имеют методы:clear(),delete(), иset().
Методы и свойства имеют то же поведение, что и эквивалентные сущности в Map, за исключением ограничения на типы ключей и значений.
Ниже приведены примеры браузерных объектов, похожих на Map, доступных только для чтения:
AudioParamMapCSSFontFeatureValuesMapEventCountsKeyboardLayoutMapMIDIInputMapMIDIOutputMapRTCStatsReport
Конструктор
-
Map() - Создает новый объект
Map.
Статические свойства
-
Map[Symbol.species] - Функция-конструктор, используемая для создания производных объектов.
Статические методы
-
Map.groupBy() - Группирует элементы заданного итерируемого объекта, используя значения, возвращаемые предоставленной функцией обратного вызова. Конечный возвращаемый
Mapиспользует уникальные значения из тестовой функции в качестве ключей, которые могут быть использованы для получения массива элементов в каждой группе.
Свойства экземпляра
Эти свойства определены в Map.prototype и используются всеми экземплярами Map.
-
Map.prototype.constructor - Функция-конструктор, которая создала объект экземпляра. Для экземпляров
Mapначальным значением является конструкторMap. -
Map.prototype.size - Возвращает количество пар ключ/значение в объекте
Map. -
Map.prototype[Symbol.toStringTag] - Начальным значением свойства
[Symbol.toStringTag]является строка"Map". Это свойство используется вObject.prototype.toString().
Методы экземпляра
-
Map.prototype.clear() - Удаляет все пары ключ-значение из объекта
Map. -
Map.prototype.delete() - Удаляет запись, указанную ключом, из этого
Map. -
Map.prototype.entries() - Возвращает новый объект Iterator, который содержит массив из двух элементов
[key, value]для каждого элемента в объектеMapв порядке вставки. -
Map.prototype.forEach() - Вызывает
callbackFnодин раз для каждой пары ключ-значение, присутствующей в объектеMap, в порядке вставки. Если параметрthisArgпредоставленforEach, он будет использоваться в качестве значенияthisдля каждого обратного вызова. -
Map.prototype.get() - Возвращает значение, соответствующее ключу в этом
Map, илиundefined, если такого ключа нет. -
Map.prototype.getOrInsert() - Возвращает значение, соответствующее указанному ключу в этом
Map. Если ключ отсутствует, он вставляет новую запись с ключом и заданным значением по умолчанию и возвращает вставленное значение. -
Map.prototype.getOrInsertComputed() - Возвращает значение, соответствующее указанному ключу в этом
Map. Если ключ отсутствует, он вставляет новую запись с ключом и значением по умолчанию, вычисленным из заданного обратного вызова, и возвращает вставленное значение. -
Map.prototype.has() - Возвращает логическое значение, указывающее, существует ли запись с указанным ключом в этом
Mapили нет. -
Map.prototype.keys() - Возвращает новый объект Iterator, который содержит ключи для каждого элемента в объекте
Mapв порядке вставки. -
Map.prototype.set() - Добавляет новую запись с указанным ключом и значением в этот
Mapили обновляет существующую запись, если ключ уже существует. -
Map.prototype.values() - Возвращает новый объект Iterator, который содержит значения для каждого элемента в объекте
Mapв порядке вставки. -
Map.prototype[Symbol.iterator]() - Возвращает новый объект Iterator, который содержит массив из двух элементов
[key, value]для каждого элемента в объектеMapв порядке вставки.
Примеры
Использование объекта Map
const myMap = new Map();
const keyString = "a string";
const keyObj = {};
const keyFunc = () => {};
// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");
console.log(myMap.size); // 3
// getting the values
console.log(myMap.get(keyString)); // "value associated with 'a string'"
console.log(myMap.get(keyObj)); // "value associated with keyObj"
console.log(myMap.get(keyFunc)); // "value associated with keyFunc"
console.log(myMap.get("a string")); // "value associated with 'a string'", because keyString === 'a string'
console.log(myMap.get({})); // undefined, because keyObj !== {}
console.log(myMap.get(() => {})); // undefined, because keyFunc !== () => {}
Использование NaN в качестве ключей Map
NaN также может использоваться в качестве ключа. Несмотря на то, что каждый NaN не равен самому себе (NaN !== NaN истинно), следующий пример работает, потому что NaN неотличимы друг от друга:
const myMap = new Map();
myMap.set(NaN, "not a number");
myMap.get(NaN);
// "not a number"
const otherNaN = Number("foo");
myMap.get(otherNaN);
// "not a number"
Итерация Map с помощью for...of
Map можно итерировать с помощью цикла for...of:
const myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (const [key, value] of myMap) {
console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one
for (const key of myMap.keys()) {
console.log(key);
}
// 0
// 1
for (const value of myMap.values()) {
console.log(value);
}
// zero
// one
for (const [key, value] of myMap.entries()) {
console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one
Итерация Map с помощью forEach()
Map можно итерировать с помощью метода forEach():
myMap.forEach((value, key) => {
console.log(`${key} = ${value}`);
});
// 0 = zero
// 1 = one
Связь с объектами Array
const kvArray = [
["key1", "value1"],
["key2", "value2"],
];
// Use the regular Map constructor to transform a 2D key-value Array into a map
const myMap = new Map(kvArray);
console.log(myMap.get("key1")); // "value1"
// Use Array.from() to transform a map into a 2D key-value Array
console.log(Array.from(myMap)); // Will show you exactly the same Array as kvArray
// A succinct way to do the same, using the spread syntax
console.log([...myMap]);
// Or use the keys() or values() iterators, and convert them to an array
console.log(Array.from(myMap.keys())); // ["key1", "key2"]
Клонирование и слияние Map
Подобно Array, Map могут быть клонированы:
const original = new Map([[1, "one"]]); const clone = new Map(original); console.log(clone.get(1)); // one console.log(original === clone); // false (useful for shallow comparison)
Примечание: Имейте в виду, что сами данные не клонируются. Другими словами, это только поверхностная копия Map.
Map могут быть объединены, сохраняя уникальность ключей:
const first = new Map([ [1, "one"], [2, "two"], [3, "three"], ]); const second = new Map([ [1, "uno"], [2, "dos"], ]); // Merge two maps. The last repeated key wins. // Spread syntax essentially converts a Map to an Array const merged = new Map([...first, ...second]); console.log(merged.get(1)); // uno console.log(merged.get(2)); // dos console.log(merged.get(3)); // three
Map также могут быть объединены с массивами:
const first = new Map([ [1, "one"], [2, "two"], [3, "three"], ]); const second = new Map([ [1, "uno"], [2, "dos"], ]); // Merge maps with an array. The last repeated key wins. const merged = new Map([...first, ...second, [1, "un"]]); console.log(merged.get(1)); // un console.log(merged.get(2)); // dos console.log(merged.get(3)); // three
Спецификации
Совместимость с браузерами
| Десктопные | Мобильные | Серверные | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
Map |
38 |
12 |
13 |
25 |
8 |
38 |
14 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
@@iterator |
38 |
12 |
36
27–36Используется свойство-заполнитель с именем@@iterator.17–27Используется свойство-заполнитель с именемiterator. |
25 |
10 |
38 |
36
27–36Используется свойство-заполнитель с именем@@iterator.17–27Используется свойство-заполнитель с именемiterator. |
25 |
10 |
3.0 |
38 |
10 |
1.0.0 |
1.0 |
0.12.0 |
@@species |
51 |
13 |
41 |
38 |
10 |
51 |
41 |
41 |
10 |
5.0 |
51 |
10 |
1.0.0 |
1.0 |
6.5.0 |
Map |
38 |
12 |
13 |
25 |
8 |
38 |
14 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
clear |
38 |
12 |
19 |
25 |
8 |
38 |
19 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
delete |
38 |
12 |
13 |
25 |
8 |
38 |
14 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
entries |
38 |
12 |
20 |
25 |
8 |
38 |
20 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
forEach |
38 |
12 |
25 |
25 |
8 |
38 |
25 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
get |
38 |
12 |
13 |
25 |
8 |
38 |
14 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
getOrInsert |
145 |
145 |
144 |
129 |
26.2 |
145 |
144 |
96 |
26.2 |
Нет |
145 |
26.2 |
1.2.20 |
2.6.7 |
26.0.0 |
getOrInsertComputed |
145 |
145 |
144 |
129 |
26.2 |
145 |
144 |
96 |
26.2 |
Нет |
145 |
26.2 |
1.2.20 |
2.6.7 |
26.0.0 |
groupBy |
117 |
117 |
119 |
103 |
17.4
16.4–17.4
|
117 |
119 |
78 |
17.4
16.4–17.4
|
24.0 |
117 |
17.4
16.4–17.4
|
1.0.19 |
1.37 |
21.0.0 |
has |
38 |
12 |
13 |
25 |
8 |
38 |
14 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
key_equality_for_zeros |
38 |
12 |
29 |
25 |
9 |
38 |
29 |
25 |
9 |
3.0 |
38 |
9 |
1.0.0 |
1.0 |
4.0.0 |
keys |
38 |
12 |
20 |
25 |
8 |
38 |
20 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
set |
38 |
12 |
13 |
25 |
8 |
38 |
14 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
size |
38 |
12 |
19Начиная с Firefox 13 по Firefox 18 свойствоsize было реализовано как метод Map.prototype.size(), что было изменено на свойство в более поздних версиях для соответствия спецификации ECMAScript 2015. |
25 |
8 |
38 |
19Начиная с Firefox for Android 14 по Firefox for Android 18 свойствоsize было реализовано как метод Map.prototype.size(), что было изменено на свойство в более поздних версиях для соответствия спецификации ECMAScript 2015. |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
values |
38 |
12 |
20 |
25 |
8 |
38 |
20 |
25 |
8 |
3.0 |
38 |
8 |
1.0.0 |
1.0 |
0.12.0 |
См. также
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map