С появлением ES2015 в JavaScript появился новый тип объектов для работы с парами ключ-значение. Называется Map
. В качестве ключей и значений можно использовать любой объект. В свою очередь, стандартные объекты допускают использование только строк в качестве ключей.
Частичный перевод статьи “Storing Key-Value Pairs With JavaScript Maps” с сайта medium.com
Манипуляции
Использовать Map
довольно просто. Например:
let map = new Map(); map.set('key-1', 'Value 1'); map.set('key-2', 'Any value 2'); map.set('the-key-3', 'Some value for 3');
Метод set
устанавливает конкретную пару ключ-значение, но если нужно установить сразу много значений при инициализации переменной map – можно воспользоваться возможностью конструктора Map и передать все данные в него в виде вложенного массива, где первый элемент – ключ, второй – значение. Например:
const pairs = [ ['a', 1], ['b', 2], ['c', 3] ] let map = new Map(pairs);
Это эквивалентно трем вызовам метода set
.
Чтобы получить количество пар ключ-значение содержащихся в Map
можно возпользоваться свойством size
:
let count = map.size; // 3
Метод get
используется для получения значения по его ключу:
map.get('a'); // 1 map.get('b'); // 2 map.get('c'); // 3
Если ключ не существует то возвратится undefined:
map.get('d'); // undefined
Метод delete используется для удаления значения по ключу:
map.delete('a');
Если ключ уже существует в Map, то метод set перезапишет старое значение новым:
map.get('b'); // 2 map.set('b', 4); map.get('b'); // 4
Чтобы удалить все пары ключ-значение из Map
, используется метод clear
:
map.clear(); map.size; // 0
Итерирование
Элементы Map
итерируемы в порядке вставки. Например, можно использовать цикл for...of
или forEach
.
let map = new Map(); map.set('hi', 'Hello'); map.set('greeting', 'How are you doing?'); map.set('bye', 'Bye'); for (let [key, value] of map) { console.log(`${key} - ${value}`); } map.forEach(function(value, key) { console.log(`${key} => ${value}`); });
Сравнение Map vs Object
Объекты похожи на Map. Они оба позволяют устанавливать значения по ключам, получать, удалять эти значения. Но у Map есть ряд преимуществ:
- Ключами значений в Map могут быть любые значения, в том числе функции, объекты и примитивные типы.
- Ключи в Map упорядочены в порядке вставки.
- Для получения количества элементов Map существует свойство size.
- Map – итерируемый объект, в то время как Объект требует ручного получения списка ключей для последующей обработки.
- Объект имеет прототип, следовательно имеет набор стандартных ключей, которые могут при неосторожности конфликтовать с вашими ключами.
- Map более производительный в сравнении с Объектами.
Другие примеры использования Map
const myMap = new Map(); const 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 !== {} ({} — это литеральная нотация конструктора класса Object) myMap.get(function() {}) // undefined, потому что keyFunc !== function () {}
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
Работа с массивами
const kvArray = [['key1', 'value1'], ['key2', 'value2']]; // Используйте конструктор Map для преобразования двумерных массивов в Map const myMap = new Map(kvArray); myMap.get('key1'); // вернёт “value1” // Используйте функцию Array.from для трансформации Map в двумерный key-value массив console.log(Array.from(myMap)); // Выведет точно такой же массив как kvArray // Или используйте итераторы keys или values чтобы преобразовать ключи или значения в массивы console.log(Array.from(myMap.keys())); // Выведет ['key1', 'key2']
Клонирование и объединение
const original = new Map([ [1, 'one'] ]); const clone = new Map(original); console.log(clone.get(1)); // one console.log(original === clone); // false.
const first = new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]); const second = new Map([ [1, 'uno'], [2, 'dos'] ]); // Слияние двух Map. Взят будет последний повторившийся ключ. // Оператор Spread по сути преобразует Map в массив const merged = new Map([...first, ...second]); console.log(merged.get(1)); // uno console.log(merged.get(2)); // dos console.log(merged.get(3)); // three
const first = new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]); const second = new Map([ [1, 'uno'], [2, 'dos'] ]); // Слияние Map и массива. Как и при слиянии двух Map - взят будет последний повторившийся ключ. const 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