В прошлом, когда дело касалось коллекций, JavaScript был ограничен. В то время как другие языки предлагают списки, наборы, ассоциативные карты и словари, JavaScript предлагает только массивы. Программистам на JavaScript пришлось найти обходной путь для создания наборов или карт, что затрудняло поддержку кода.
Теперь, с ES6, JavaScript предлагает новые встроенные классы для наборов и карт, которые значительно упрощают поддержку программирования. В этом руководстве мы подробно познакомим вас с отображением и настройкой, а также с примерами кода, вариантами использования и практическими упражнениями. Это руководство идеально подходит для разработчиков JavaScript, которые хотят усовершенствовать свои навыки работы с JavaScript.
- Что есть map?
- Как пользоваться картой
- Перебирать карты
- Инициализировать карту с итерируемым объектом
- Получить элемент с карты по ключу
- Получить количество элементов на карте
- Преобразование ключей или значений карты в массив
- Что есть set?
- Как использовать set
- filter/ mapс наборами
- Get the size of a Set
- Удалить элементы из набора
- Другие важные методы Set
- Практическое упражнение с map
- Разбивка решения
- Что изучать дальше
Что есть map?
До ES6 разработчики JavaScript использовали объекты для сопоставления ключей со значениями. Однако использование объекта в качестве карты имеет свои ограничения. Например:
- Не существует надежного способа перебора ключей, и keys()метод преобразует поля в строки, что приводит к конфликту ключей.
- Нет простого способа добавить новые ключи и значения
ES6 представил несколько новых встроенных классов , включая называемый тип коллекцииMap , который может содержать пары ключ-значение любого типа. В отличие от объектного подхода, новый объект Map может запоминать порядок вставки ключей.
Проще говоря, JavaScript Map- это ассоциативный набор различных ключей и значений. И ключи, и значения могут быть любым примитивом или объектом. Это важная структура данных, которая может быть полезна для многих целей.
Примечание: A WeakMapпохож на Map, но все ключи a WeakMapявляются объектами.
Для создания нового Mapмы используем следующий синтаксис:
let map = new Map([iterable]);
Давайте применим это на практике на более сложном примере. Ниже у нас есть карта, в которой имена являются ключами, а оценки — значениями.
‘use strict’;//START:DEFINEconst scores =new Map([[‘Sara’, 12], [‘Bob’, 11], [‘Jill’, 15], [‘Bruce’, 14]]);scores.set(‘Jake’, 14);console.log(scores.size);//END:DEFINE
- scores Карта была инициализирована с именами и оценки. Начальные данные могут быть любыми итеративными с парой ключей и значений.
- Мы добавляем ключ и значение на карту, используя set()метод (строка 7)
- Чтобы выяснить, сколько ключей в настоящее время находится на карте, мы используем свойство size (строка 9).
Примечание: Map.has(key) выше будет возвращено логическое значение, чтобы указать, находится ли элемент, связанный с указанным ключом, на карте.
Как пользоваться картой
Когда мы узнаем, как создавать карты с помощью JavaScript, мы сможем многое сделать с ними.
Перебирать карты
Во-первых, давайте узнаем об итерации с помощью карт. Мы можем использовать 3 метода:
- map.keys(): возвращает итерацию для ключей
- map.entries(): возвращает итерацию для записей [key, value]
- map.values(): возвращает итерацию для значений
Мы можем перебирать коллекцию ключей и значений с помощью entries()метода, который возвращает итерацию, поэтому мы можем использовать улучшенное for loopвместе с деструктуризацией.
Например, ниже мы извлекаем имя и оценку для каждой пары ключ-значение:
‘use strict’;//START:DEFINEconst scores =new Map([[‘Sara’, 12], [‘Bob’, 11], [‘Jill’, 15], [‘Bruce’, 14]]);scores.set(‘Jake’, 14);//END:DEFINEfor(const [name, score] of scores.entries()) {console.log(`${name} : ${score}`);}
Мы также можем использовать forEachметод, который является внутренним итератором.
‘use strict’;//START:DEFINEconst scores =new Map([[‘Sara’, 12], [‘Bob’, 11], [‘Jill’, 15], [‘Bruce’, 14]]);scores.set(‘Jake’, 14);//END:DEFINEscores.forEach((score, name) => console.log(`${name} : ${score}`));
Первый параметр, который получает функция, — это значение ключа, который появляется как второй параметр. Тот же forEach()метод можно использовать для перебора только значений:
‘use strict’;//START:DEFINEconst scores =new Map([[‘Sara’, 12], [‘Bob’, 11], [‘Jill’, 15], [‘Bruce’, 14]]);scores.set(‘Jake’, 14);//END:DEFINEscores.forEach(score => console.log(score));
Если вы получите только один параметр, это будет значение, а если вы получите два параметра, то это будет значение и ключ для каждой пары ключ-значение.
Инициализировать карту с итерируемым объектом
Вы также можете передать конструктору итерируемый объект Map():
let userRoles = new Map([[sarah, ‘admin’],[bob, ‘editor’],[jill, ‘subscriber’]]);
Получить элемент с карты по ключу
Мы можем получить элементы с карты по ключу с помощью get()метода:
Но если вы передадите ключ, которого нет на этой карте, он вернет undefined.
userRoles.get(sarah); // admin
Но если вы передадите ключ, которого нет на этой карте, он вернет undefined.
let foo = {name: 'Foo'}; userRoles.get(foo); //undefined
Получить количество элементов на карте
Мы можем использовать sizeсвойство, чтобы получить количество элементов на наших картах.
console.log(userRoles.size); // 3
Преобразование ключей или значений карты в массив
Иногда вам может понадобиться работать с массивом вместо итерируемого объекта. Мы можем использовать оператор распространения, чтобы преобразовать ключи для каждого элемента в новый массив.
var keys = [...userRoles.keys()]; console.log(keys);
Этот фрагмент кода преобразует значения элементов в массив:
var roles = [...userRoles.values()]; console.log(roles);
Другие важные методы карты
- clear(): удаляет элементы из объекта карты.
- map.set(key, value): сохраняет значение по ключу
- delete(key): удаляет определенный элемент (указанный ключом)
- set(key, value): устанавливает значение ключа и возвращает объект карты. Может быть связан с другими методами.
- forEach(callback[, thisArg]): вызывает обратный вызов для каждой пары «ключ-значение» в порядке вставки. thisArgПараметр является необязательным и устанавливает thisзначение для каждого обратного вызова.
- has(key): возвращает, trueесли значение, связанное с ключом, существует, в противном случае false.
- keys(): возвращает новый итератор с ключами для элементов в порядке вставки.
- values(): возвращает новый объект итератора со значениями для каждого элемента в порядке вставки.
- map.size: возвращает текущее количество элементов
Что есть set?
Set- еще одна новая коллекция, представленная ES6. ArrayКласс JavaScript может работать с упорядоченным набором данных, но не так хорошо с неупорядоченными коллекциями или когда значения хранятся в коллекции являются уникальными. Вот почему появился JavaScript Set.
A set- это уникальный набор примитивов и объектов, дублирование которых не допускается. Мы можем либо создать пустой набор и добавить объекты, либо инициализировать набор содержимым итерации (например, массива).
Давайте рассмотрим это на примере. Ниже у нас есть набор имен с пятью значениями. Одно из значений не входит в набор из-за дублирования.
‘use strict’;//START:CREATEconst names = new Set([‘Jack’, ‘Jill’, ‘Jake’, ‘Jack’, ‘Sara’]);//END:CREATE//START:SIZEconsole.log(names.size);//END:SIZE
Мы можем добавлять элементы в существующий набор, как показано ниже:
names.add('Matt');
add()Метод возвращает поток Set, который является полезным для цепных операций, таких как более звонков add()или других методов Set:
names.add('Kate') .add('Kara');
Как использовать set
Как только мы выясним, как создавать наборы, с ними легко работать. Сначала посмотрим на встроенные функции для наборов:
- has(): чтобы проверить, есть ли в наборе определенный элемент.
- clear(): очистить существующий набор или удалить существующий элемент с помощью delete()метода.
- keys(): получить все значения из набора
- entries(): для перебора Set с использованием расширенного цикла for, как показано ниже:
‘use strict’;//START:CREATEconst names = new Set([‘Jack’, ‘Jill’, ‘Jake’, ‘Jack’, ‘Sara’]);//END:CREATE//START:ADDnames.add(‘Mike’);//END:ADD//START:ADD2names.add(‘Kate’).add(‘Kara’);//END:ADD2console.log(names.has(‘Brad’));console.log(names.entries());console.log(names.keys());console.log(names.values());//START:ITERATE1for(const name of names) {console.log(name);}//END:ITERATE1
filter/ mapс наборами
Set еще не предлагает таких методов, как filter()и map(), но мы можем создать массив из набора и использовать методы функционального стиля для этого нового массива.
Например, ниже мы используем методы filter(), map()и, forEach()чтобы выбрать только имена, начинающиеся с, Jа затем преобразовать их в верхний регистр.
‘use strict’;//START:CREATEconst names = new Set([‘Jack’, ‘Jill’, ‘Jake’, ‘Jack’, ‘Sara’]);//END:CREATE//START:ADDnames.add(‘Mike’);//END:ADD//START:ADD2names.add(‘Kate’).add(‘Kara’);//END:ADD2//START:FILTER[…names].filter(name => name.startsWith(‘J’)).map(name => name.toUpperCase()).forEach(name => console.log(name));//END:FILTER
Get the size of a Set
Используйте sizeсвойство объекта Set, чтобы вернуть его размер.
let size = chars.size; console.log(size);// 3
Удалить элементы из набора
Чтобы удалить элемент из набора, используйте delete()метод.
chars.delete('f'); console.log(chars); // Set {"a", "b", "c", "d", "e"}
А чтобы удалить все элементы набора, используйте clear()метод:
chars.clear(); console.log(chars); // Set{}
Вызов функции обратного вызова для каждого элемента
Чтобы вызвать обратный вызов для каждого элемента вашего набора, используйте forEach()метод.
roles.forEach(role => console.log(role.toUpperCase()));
Другие важные методы Set
- new Set(iterable): создает набор.
- set.add(value): добавляет заданное значение и возвращает набор
- set.has(value): возвращается, trueесли значение существует в наборе, в противном случае возвращается false.
- set.clear(): удаляет все из набора
Практическое упражнение с map
Чтобы закрепить ваше обучение, давайте выполним практическое упражнение с картой на JavaScript. Используйте Mapдля получения желаемого результата, как указано ниже. При создании объекта createTodo()он должен возвращать элемент карты.
Входные звонки | Выход |
console.log(todo.get(‘learn JavaScript’)); | Выполнено |
console.log(todo.get(‘write elegant code’)); | работа в процессе |
console.log(todo.get(‘automate tests’)); | работа в процессе |
console.log(completedCount(todo)); | 1 |
Ниже приводится решение этой проблемы. Сначала попробуйте сами.
‘use strict’;const createTodo = function() {const todo = new Map();return todo;};const completedCount = function(map) {return;};const todo = createTodo(); //Returns a Map
Разбивка решения
Начнем с создания элемента карты. MapОбъект todoсоздается на линии 4 , используя встроенный класс. Вы можете видеть, что объект карты todoвызывается Map.get()с разными ключами для получения их значений. Это означает, что нам нужно добавить все ключи и значения.
Мы добавляем новый элемент todoс ключами и соответствующими значениями. В строках 5-7 мы добавляем новые элементы, устанавливая значения для ключей.
Для completedCount()мы определяем новую функцию с параметром объекта карты. Функция вернет количество выполненных задач. Итак, по сути, мы фильтруем все значения элементов в объекте карты, чтобы получить элементы со значением, равным done(см. Строку 14).
В строке 15 свойство length используется для подсчета количества специальных элементов.
Что изучать дальше
Map и set — ценные дополнения к JavaScript, они сделают ваш код более чистым и легким в обслуживании. Теперь, когда у вас есть четкое понимание карты и набора, вы готовы заняться другими функциями, добавленными в ES6 и не только.
Вот несколько концепций, которые следует рассмотреть при модернизации вашего JavaScript:
- Async и Await ( обещания )
- Метапрограммирование
- Объектные литералы
- Стрелочные функции