Объект Map в JS

В этой статье вы познакомитесь с новой структурой данных в JavaScript — объектом Map.

В JavaScript ES6 появились две новые структуры данных — Map и WeakMap.

Map похож на объекты в JavaScript, то есть позволяет хранить элементы в виде пары ключ/значение.

Однако в отличие от объекта, Map может содержать в качестве ключа объекты, функции и другие типы данных.

Создание объекта Map

Для создания Map нужно использовать конструктор new Map(). Например:

// создание Map
const map1 = new Map(); // пустой map
console.log(map1); // Вывод: Map {}

Вставка элемента в Map

После создания Map в него можно добавлять объекты — с помощью метода set().

// создаем map
let map1 = new Map();

// вставляет пару ключ/значение
map1.set('инфо', {name: 'Андрей', age: 26});
console.log(map1); // Map {"инфо" => {name: "Андрей", age: 26}}

В качестве ключей также можно использовать объекты или функции. Например:

// Map с объектом в качестве ключа
let map2 = new Map();

let obj = {};
map2.set(obj, {name: 'Андрей', age: "26"});

console.log(map2); // Вывод: Map {{} => {name: "Андрей", age: "26"}}

Доступ к элементам Map

Получить элемент объекта Map можно с помощью метода get(). Например:

let map1 = new Map();
map1.set('инфо', {name: 'Андрей', age: "26"});

// доступ к элементам Map
console.log(map1.get('инфо')); // Вывод: {name: "Андрей", age: "26"}

Проверка наличия элемента в Map

Чтобы проверить, находится ли элемент в Map, используют метод has(). Например:

let map1 = new Map();
map1.set('инфо', {name: 'Андрей', age: "26"});

// проверяем, есть ли элемент в Map
console.log(map1.has('инфо')); // Вывод: true

Удаление элементов из Map

Для удаления элементов из Map можно использовать методы clear() и delete().

Метод delete() возвращает true, если указанная пара ключ/значение существует и была удалена. Иначе возвращает false.

let map1 = new Map();
map1.set('инфо', {name: 'Андрей', age: "26"});

// удаляем определенный элемент
map1.delete('адрес'); // false
console.log(map1); // Вывод: Map {"инфо" => {name: "Андрей", age: "26"}} 

map1.delete('инфо'); // true
console.log(map1); // Вывод: Map {}

Метод clear() удаляет все пары ключ/значение из объекта Map. 

let map1 = new Map();
map1.set('инфо', {name: 'Андрей', age: "26"});

// удаляем все элементы
map1.clear();
console.log(map1); // Вывод: Map {}

Размер объекта Map

Получить информацию о количестве элементов в Map можно через свойство size. Например:

let map1 = new Map();
map1.set('инфо', {name: 'Андрей', age: "26"});

console.log(map1.size); // Вывод: 1

Перебор элементов Map

Перебирать элементы Map можно с помощью цикла for...of или метода forEach(). Доступ к элементам осуществляется в в том же порядке, в каком происходило добавление элементов.

let map1 = new Map();
map1.set('имя', 'Андрей');
map1.set('возраст', '27');

// перебираем элементы Map
for (let [key, value] of map1) {
    console.log(key + ': ' + value);
}

Вывод

имя: Андрей
возраст: 27

То же самое можно сделать с помощью метода forEach(). Например:

// используем метод forEach()
let map1 = new Map();
map1.set('имя', 'Андрей');
map1.set('возраст', '27');

// перебираем элементы
map1.forEach(function(value, key) {
  console.log(key + ': ' + value)
})

Перебор ключей Map

Перебрать ключи объекта Map можно с помощью метода keys(). Например:

let map1 = new Map();
map1.set('имя', 'Андрей');
map1.set('возраст', '27');

// перебор ключей Map
for (let key of map1.keys()) {
  console.log(key)
}

Вывод

имя
возраст

Перебор значений Map

Перебрать значений объекта Map можно с помощью метода values(). Например:

let map1 = new Map();
map1.set('имя', 'Андрей');
map1.set('возраст', '27');

// перебираем значения Map
for (let values of map1.values()) {
    console.log(values);
}

Вывод

Андрей
27

Получение пары ключ/значение объекта Map

При итерировании по объекту Map можно получать пары ключ/значение с помощью метода entries(). Например:

let map1 = new Map();
map1.set('имя', 'Андрей');
map1.set('возраст', '27');

// перебор Map
for (let elem of map1.entries()) {
    console.log(`${elem[0]}: ${elem[1]}`);
}

Вывод

имя: Андрей
возраст: 27

Чем Map отличается от объекта

Map Объект
Ключи: объекты и другие типы данных. Ключи: только типа string и symbol.
Перебор и по значениям, и по ключам. Перебор только по ключам.
Размер — в свойстве size. Размер задается вручную.
Эффективно работает, когда нужно часто добавлять или удалять элементы. Плохо работает, когда нужно часто добавлять или удалять элементы.

Объект WeakMap

Объект WeakMap похож на Map. Отличие: WeakMap может содержать только объекты в качестве ключей. Например:

const weakMap = new WeakMap();
console.log(weakMap); // Вывод: WeakMap {} 

let obj = {};

// добавление объектов (элементов) в WeakMap
weakMap.set(obj, 'привет');

console.log(weakMap); // Выводы: WeakMap {{} => "привет"}

Если вы попытаетесь добавить в качестве ключа другой тип данных, WeakMap выдаст ошибку. Например:

const weakMap = new WeakMap();

// добавление строки в качестве ключа в WeakMap
weakMap.set('obj', 'привет'); // TypeError: Attempted to set a non-object key in a WeakMap

Методы WeakMap

У WeakMaps есть следующие методы: get(), set(), delete() и has()

Разберем эти методы на примерах:

const weakMap = new WeakMap();
console.log(weakMap); // Вывод: WeakMap {} 

let obj = {};

// добавляем объект (элемент) в WeakMap
weakMap.set(obj, 'привет');

console.log(weakMap); // Вывод: WeakMap {{} => "привет"}

// получаем элементы WeakMap
console.log(weakMap.get(obj)); // Вывод: привет

// проверяем, есть ли элемент в WeakMap
console.log(weakMap.has(obj)); // Вывод: true

// удаляем элемент из WeakMap
console.log(weakMap.delete(obj)); // Вывод: true

console.log(weakMap); // Вывод: WeakMap {} 

WeakMap не поддерживает перебор

В отличие от Map, перебрать элементы WeakMap нельзя. Например:

const weakMap = new WeakMap();
console.log(weakMap); // Вывод: WeakMap {} 

let obj = {};

// добавляем объект (элемент) в WeakMap
weakMap.set(obj, 'привет');


// перебираем элементы WeakMap
for (let i of weakMap) {

    console.log(i);  // возникает ошибка TypeError
}
Проверьте себя
1. Чем Map отличается от обычного объекта в JavaScript?
AMap хранит только строки
BMap допускает ключи любого типа, включая объекты и функции
CMap не поддерживает перебор
DMap быстрее только для строковых ключей
2. Какой метод Map используется для добавления элемента?
Aadd()
Bset()
Cput()
Dinsert()
3. Как получить количество элементов в объекте Map?
Amap.length
Bmap.count
Cmap.total
Dmap.size
4. Что отличает WeakMap от Map?
AWeakMap поддерживает перебор
BWeakMap быстрее при работе со строками
CWeakMap допускает только объекты в качестве ключей
DWeakMap может хранить примитивные значения