Объект Map

Объекты Map хранят пары ключ-значение. Любое значение (объект или примитивное значение) может использоваться как ключ или как значение.

Разница между Map и Object

  • Ключи Object могут быть только строками или Symbols, но ключи Map могут быть любым значением.
  • Пары ключ-значение в Map упорядочены (принцип FIFO), тогда как ключи, добавленные в объект, — нет.
  • Количество пар ключ-значение в Map можно получить из свойства size, а количество в Object можно только подсчитать вручную.
  • У объектов есть собственный прототип, и имена ключей в цепочке прототипов могут конфликтовать с именами ключей, которые вы задаёте на объекте.

Ключ в Map

Ключ — это строка

var myMap = new Map(); var keyString = "a string"; myMap.set(keyString, "The value associated with the key 'a string'"); myMap.get(keyString); //"The value associated with the key 'a string'" myMap.get("a string"); //"The value associated with the key 'a string'" //Потому что keyString === 'a string'

Ключ — это объект

var myMap = new Map(); var keyObj = {}, myMap.set(keyObj, "Значение, связанное с ключом keyObj");  myMap.get(keyObj); //"Значение, связанное с ключом keyObj" myMap.get({}); //undefined, потому что keyObj !== {}

Ключ — это функция

var myMap = new Map(); var keyFunc = function () {}, //Function myMap.set(keyFunc, "Значение, связанное с ключом keyFunc"); myMap.get(keyFunc); //"Значение, связанное с ключом keyFunc" myMap.get(function() {}) //undefined, потому что keyFunc !== function () {}

Ключ — это NaN

var myMap = new Map(); myMap.set(NaN, "не число"); myMap.get(NaN); // "не число" var otherNaN = Number("foo"); myMap.get(otherNaN); // "not a number"

Хотя NaN не равен ни одному значению, даже самому себе (NaN !== NaN возвращает true), в качестве ключа Map NaN не имеет значения.

Итерация Map

Чтобы перебрать Map, следующие два способа являются наиболее мощными.

for...of

var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one"); //Будет показано два лога. Один — "0 = zero", а другой — "1 = one". for (var [key, value] of myMap) {   console.log(key + " = " + value); } for (var [key, value] of myMap.entries()) { console.log(key + " = " + value); } /*Метод entries возвращает новый объект Iterator, который содержит массив [key, value] каждого элемента в объекте Map в порядке вставки.*/ //Будет показано два лога. Один — "0", а другой — "1". for (var key of myMap.keys()) {   console.log(key); } /*Метод keys возвращает новый объект Iterator, содержащий ключи каждого элемента в объекте Map в порядке вставки.*/ //Будет выведено два лога. Один — "zero", а другой — "one". for (var value of myMap.values()) {   console.log(value); } /*Метод values возвращает новый объект Iterator, содержащий значения каждого элемента в объекте Map в порядке вставки.*/

forEach()

var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one"); //Будет показано два лога. Один — "0 = zero", а другой — "1 = one". myMap.forEach(function(value, key) { console.log(key + " = " + value); }, myMap)

Операции с объектами Map

Преобразование между Map и Array

var kvArray = [["key1", "value1"], ["key2", "value2"]]; //Конструктор Map может преобразовать двумерный массив пар ключ-значение в объект Map. var myMap = new Map(kvArray); //Использование функции Array.from позволяет преобразовать объект Map в двумерный массив пар ключ-значение. var outArray = Array.from(myMap);

Клонирование Map

var myMap1 = new Map([["key1", "value1"], ["key2", "value2"]]); var myMap2 = new Map(myMap1); console.log(original === clone); //Выводит false. Конструктор объекта Map создаёт экземпляр, а итерация создаёт новый объект.

Объединение Map

var first = new Map([[1, 'one'], [2, 'two'], [3, 'three'],]); var second = new Map([[1, 'uno'], [2, 'dos']]); //При объединении двух объектов Map, если есть повторяющиеся ключи, более поздний переопределяет более ранний. Соответствующие значения — uno, dos, three. var merged = new Map([...first, ...second]);

Объект Set

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

Особые значения в Set

Значения, хранящиеся в объекте Set, всегда уникальны, поэтому необходимо определять, строго ли равны два значения. Есть несколько особых значений, требующих особой обработки:

  • +0 и -0 строго равны при определении уникальности для хранения, поэтому они не дублируются;
  • undefined и undefined строго равны, поэтому они не дублируются;
  • NaN и NaN не строго равны, но в Set можно сохранить только одно, поэтому они не дублируются.

Code

let mySet = new Set(); mySet.add(1); // Set(1) {1} mySet.add(5); // Set(2) {1, 5} mySet.add(5); //Set(2) {1, 5} Здесь это отражает уникальность значений. mySet.add("some text"); //Set(3) {1, 5, "some text"} Здесь это отражает разнообразие типов. var o = {a: 1, b: 2}; mySet.add(o); mySet.add({a: 1, b: 2}); // Set(5) {1, 5, "some text", {…}, {…}} //Здесь это отражает, что ссылки на объекты различаются и не строго равны; даже если значения одинаковы, Set всё равно может их хранить.

Преобразование типов

Массив

//Преобразование Array в Set var mySet = new Set(["value1", "value2", "value3"]); //Используйте оператор ... для преобразования Set в Array. var myArray = [...mySet]; String //Преобразование String в Set var mySet = new Set('hello');  // Set(4) {"h", "e", "l", "o"} //Примечание: метод toString в Set не может преобразовать Set в String.

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

Дедупликация массива

var mySet = new Set([1, 2, 3, 4, 4]); [...mySet]; // [1, 2, 3, 4]

Объединение

var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var union = new Set([...a, ...b]); // {1, 2, 3, 4}

Пересечение

var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}

Разница

var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var difference = new Set([...a].filter(x => !b.has(x))); // {1}