PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • Подписка
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюсPurpleMax
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • Подписка
    • AI для кодаНовое
    • Сообщество
    Главная
    Сообщество
    Map и Set в JavaScript для удобной работы с данными

    Map и Set в JavaScript для удобной работы с данными

    Аватар автора Map и Set в JavaScript для удобной работы с данными

    Валерий Шестернин

    Иконка календаря14 августа 2023

    JavaScript предлагает несколько встроенных структур данных, которые облегчают работу с коллекциями. В этой статье мы рассмотрим два таких инструмента - Map и Set, их преимущества, особенности использования, а также примеры практического применения.

    Отличие Map от Object

    Map - это вид объекта JavaScript, но в отличии от обычных объектов, ключи в Map могут быть любым типом данных, а не только строками или символами. Однако важно понимать, что для корректной работы с этой структурой данных нужно использовать специальные методы и свойства:

    • new Map() – создаёт коллекцию принимая массив или другой итерируемый объект (const myMap = new Map([[1, “a”], [2, “b”]]).
    • .set(key, value) – записывает по ключу key значение value при этом возвращая ту же коллекцию, поэтому можно строить цепочки (myMap.set(1, "a").set(2, "b")).
    • .size – возвращает текущее количество пар ключ-значение. Это количество нельзя переопределить как length у массива.
    • .get(key) – возвращает значение по ключу или undefined, если ключ key отсутствует.
    • .delete(key) – удаляет пару ключ-значение по ключу key и возвращает true если ключ key был в коллекции, в противном случае прокидывает ошибку.
    • .clear() – полностью очищает коллекцию от всех пар ключ-значение .
    • .has(key) – проверяет наличие ключа key в коллекции и возвращает ответ в виде булева значения (true если ключ найден и false если нет).
    • .keys() – возвращает итерируемый объект по ключам.
    • .values() – возвращает итерируемый объект по значениям.
    • .entries() – возвращает итерируемый объект по парам вида [key, value], этот вариант используется по умолчанию в for..of.
    • .forEach - метод для перебора Map, схожий со встроенным методом массивов.jsx

    const john = { name: "John" }; const kate = { name: "Kate" };

    const usersAge = {}; //создаем пустой объект usersAge[john] = 25; usersAge[kate] = 20; //присваиваем ключами объекты console.log(usersAge[john]); //20 console.log(usersAge); //{ '[object Object]': 20 } //несмотря на то что для john мы указали возраст 25 по ключу хранится значение 20. const usersAgeWithMap = new Map(); usersAge[john] = 25; usersAge[kate] = 20; //делаем то же самое с Map console.log(usersAgeWithMap[john]); //undefined console.log(usersAgeWithMap); //Map(0) {} //А теперь повторим действия, но с использованием методов set и get usersAgeWithMap.set(john, 25).set(kate, 20); console.log(usersAgeWithMap.get(john)); //25 console.log(usersAgeWithMap); //Map(2) { { name: 'John' } => 25, { name: 'Kate' } => 20 } usersAgeWithMap.size = 1; console.log(usersAgeWithMap); //Map(2) { { name: 'John' } => 25, { name: 'Kate' } => 20 } console.log(usersAgeWithMap.clear()); //Map(2) { { name: 'John' } => 25, { name: 'Kate' } => 20 }

        
    На примере выше мы видим, как при попытке присвоить обычному объекту ключи в виде других объектов, значение перезаписывается, а не создается новое свойство. Это происходит потому что объекты, которые мы передали как ключи, преобразуются в строку и строковое выражение обоих объектов john и kate равно друг другу(*`'[object Object]'`*). При попытке добавить в Map пары ключ-значение через прямое обращение без метода `set` (`map[key]=value`) эти пары не добавляются. Все начинает работать как задумано только при использовании специальных методов. Такое ограничение синтаксиса может показаться неудобным, ведь если мы не знаем в каком формате (Map и Object) к нам приходят данные, придется писать проверку и работать с ними по разному, но, из-за такой чувствительности к применению методов, Map становится безопаснее, ведь нельзя переназначить свойства по-умолчанию (как `length` у массива) и изменить прототип коллекции. 
    
    Map (как и Set) использует алгоритм SameValueZero для сравнения ключей. Этот алгоритм практически идентичен оператору строгого сравнения (`===`), за исключением того, что NaN считается равным NaN. Поэтому, NaN может быть использован в качестве ключа в Map. Важно отметить, что этот алгоритм не может быть изменен или модифицирован.
    
    В отличии от объектов, Map хранит пары ключ-значение в том порядке, в котором они были добавлены, что может быть полезно при переборе. 
    
    ```jsx
    const myObj = {};
    myObj["01"] = 1;
    myObj["a"] = 2;
    myObj[1] = 3;
    console.log(myObj); //{ '1': 3, '01': 1, a: 2 }
    const myMap = new Map();
    myMap.set("01", 1).set("a", 2).set(1, 3);
    console.log(myMap); //Map(3) { '01' => 1, 'a' => 2, 1 => 3 }
    

    Есть у Map и серьезные недостатки. У этой структуры данных нет встроенной поддержки сериализации или синтаксического анализа. Т.е. мы не можем просто передать Map в JSON.stringify() что бы получить строку со всеми данными или распарсить JSON и получить полную структуру Map. Придется писать свою реализацию.

    const myMap = new Map([
      ["name", "Kate"],
      ["age", 20],
    ]);
    const stringFromMap = JSON.stringify(myMap); //строка: {}
    //Map не выйдет просто так преобразовать в строку
    const objFromMap = Object.fromEntries(myMap.entries());
    //преобразуем наш Map в Object
    const stringFromMapWithObj = JSON.stringify(objFromMap); //строка: {"name":"Kate","age":20}
    //объект уже легко преобразуется в строку
    const objFromString = JSON.parse(stringFromMapWithObj); //объект: { name: 'Kate', age: 20 }
    const myNewMap = new Map(Object.entries(objFromString)); //Map(2) { 'name' => 'Kate', 'age' => 20 }
    //парсить данные формата JSON в Map так же придется через преобразование в объект
    

    В примере выше мы преобразуем Map в простые пары ключ-значение с помощью метода entries и передаем результат в метод fromEnteries глобального объекта Object что бы потом с помощью JSON.stringify преобразовать данные в строку. Что бы распарсить JSON в Map мы проводим обратные операции. Если такие конструкции кажутся слишком громоздкими, представьте, если бы ключом был объект, ведь при попытке собрать Object из такой пары наш ключ превратится в строку '[object Object]' .

    Применение Map

    Структура данных Map в JavaScript предоставляет множество возможностей и находит широкое применение в различных случаях. Вот лишь несколько примеров:

    • Частое применение Map - это сохранение связи между объектами и другими значениями. Например, если мы хотим хранить метаданные отдельно от самой сущности.
    const product1 = { id: 1, name: "coat", price: 100 };
    const product2 = { id: 2, name: "t-shirt", price: 50 };
    
    const productsMetaData = new Map();
    productsMetaData.set(product1, { creator: "John", createdAt: new Date() });
    productsMetaData.set(product2, { creator: "Kate", createdAt: new Date() });
    console.log(productsMetaData.get(product1));
    //{ creator: 'John', createdAt: <дата и время создания> }
    
    • Если Вам нужно очень часто добавлять и удалять пары ключ-значение Map хорошо оптимизирован для подобных операций и справляется в несколько раз быстрее, чем Object.
    const myObj = {};
    for (let i = 0; i <= 10000000; i++) {
      myObj[i] = i;
      delete myObj[i];
    } //выполнится за 1325 миллисекунд
    
    const myMap = new Map();
    for (let i = 0; i <= 10000000; i++) {
      myMap.set(i, i);
      myMap.delete(i);
    } //выполнится за 378 миллисекунд
    
    • Даже если в Вашем коде не создано ни одного Map, умение работать с этой структурой данных все равно может пригодиться. Map-подобные объекты используются в браузерных Web API таких как AudioParamMap, RTCStatsReport, EventCounts, KeyboardLayoutMap, MIDIInputMap и MIDIOutputMap. Такие объекты работают по принципу Map и используют те же методы, однако отличаются ограничениями на типы данных, которые могут быть использованы в качестве ключей.

    Set

    Set это коллекция уникальных значений без индексов и ключей. Для простоты понимания можно представить что Set это Map, которых хранит только значения, а не пары ключ-значение. Даже методы Set “достались” от Map, но т.к. хранятся не пары, а только само значение любого типа данных, методы .values() и .keys() у этой структуры данных полностью аналогичны, а метод .get() отсутствует. Интересно, что при переборе Set с помощью метода .forEach() или цикла for…of… функции будут доступны три аргумента: value, valueAgain (буквально “значение еще раз”) и сама коллекция.

    const mySet = new Set([1, 1, "2", "2"]); //Set(2) { 1, '2' }
    console.log(mySet.values()); //[Set Iterator] { 1, '2' }
    console.log(mySet.keys()); //[Set Iterator] { 1, '2' }
    mySet.forEach((value, valueAgain, set) => console.log(value, valueAgain, set));
    //1 1 Set(2) { 1, '2' }
    //2 2 Set(2) { 1, '2' }
    

    Для добавления нового элемента используется метод .add(value). Этот метод назван по-другому не только что бы не создавать путаницы с его названием и названием структуры данных, но и потому что работает совсем иначе. Если переданное значение уже есть в коллекции - метод не производит ни каких действий, что делает его максимально быстрым в сравнении с аналогами у других типов данных. Метод .has(value) так же производительнее, чем схожий .inclused() у массивов. При этом важно помнить, что ссылочные типы данных, так же как и в Map, следует передавать именно по ссылке.

    const mySet = new Set();
    mySet.add({ id: 1, name: "John" }).add({ id: 1, name: "John" });
    console.log(mySet); //Set(2) { { id: 1, name: 'John' }, { id: 1, name: 'John' } }
    const kate = { id: 2, name: "Kate" };
    mySet.add(kate).add(kate);
    console.log(mySet);
    //Set(3) {{ id: 1, name: 'John' },{ id: 1, name: 'John' },{ id: 2, name: 'Kate' }}
    

    Наиболее частое применение Set - создание коллекций уникальных данных из массивов. Так лаконичная строка кода с использованием Set заменит большую конструкцию с проверкой каждого элемента массива на уникальность и выполнит подобную операцию в разы быстрее.

    const myArr = [1, 1, 2, 3, 3];
    const uniqueArr = [...new Set(myArr)];//[ 1, 2, 3 ]
    

    Заключение:

    Map и Set это удобные инструменты для работы с данными в JavaScript. Они делают код более производительным, лаконичным и легким для чтения. Надеюсь данная статья была полезна для понимания столь важной темы.

    Иконка глаза9 923

    Комментарии

    0

    Постройте личный план изучения Основы разработки до уровня Middle — бесплатно!

    Основы разработки — часть карты развития Frontend, Backend, Mobile

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Основы Git

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    HTML и CSS

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    CSS Flexbox

    Антон Ларичев
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    бесплатно
    Подробнее

    Похожие статьи

    Картинка поста Профессиональное выгорание программиста: признаки и как с ним бороться
    Иконка аватараАнтон
    Иконка календаря28 октября 2026
    выгораниепродуктивностьsoft skills+ 2middleИконка уровня middle

    Профессиональное выгорание программиста: признаки и как с ним бороться

    Выгорание программиста — не абстракция, а измеримое явление: падение скорости коммитов, рост багов, ночные дедлайны. Разбираем признаки, причины и рабочие способы восстановиться.

    Иконка чипа0
    Иконка глаза121
    Иконка комментариев0
    Картинка поста Neovim + avante.nvim с Claude из России: настройка
    Иконка аватараАнтон
    Иконка календаря27 октября 2026
    AI-инструментыAnthropicразработкаmiddleИконка уровня middle

    Neovim + avante.nvim с Claude из России: настройка

    avante.nvim — плагин для Neovim, который добавляет ИИ-ассистента в стиле Cursor: боковую панель с чатом по коду, правки выделенного фрагмента и применение изменений прямо в буфер. С Claude он работает через провайдер `claude`, но из России напрямую не подключится: API Anthropic отклоняет российские адреса, а ключ оплачивается зарубежной картой. Решение — указать в конфиге плагина свой адрес API (`endpoint`) и ключ AI для кода от PurpleSchool с оплатой в рублях. Ниже — установка через lazy.nvim, актуальный конфиг, горячие клавиши и частые ошибки.

    Иконка чипа0
    Иконка глаза169
    Иконка комментариев0
    Картинка поста OpenCode: пользовательские провайдеры недоступны — что делать
    Иконка аватараАнтон
    Иконка календаря26 октября 2026
    AI-инструментыapiразработкаjuniorИконка уровня junior

    OpenCode: пользовательские провайдеры недоступны — что делать

    Ошибка «Пользовательские провайдеры недоступны на этом сервере» (в английском интерфейсе — «Custom providers are unavailable on this server») появляется в OpenCode Desktop и веб-интерфейсе OpenCode, когда вы сохраняете своего провайдера через «Настройки → Провайдеры → Пользовательский провайдер». Это ошибка самого OpenCode, а не вашего ключа, сервера или региона: в версиях 2.0.x форма сохранения не подключена к серверу и выдаёт эту ошибку при любых введённых данных. VPN и смена ключа не помогут. Решение — описать провайдера в файле `opencode.json`: так он работает и в Desktop, и в терминальной версии. Ниже — что именно сломано, готовые конфиги для Claude, GPT и Qwen и что делать, если модели не появились.

    Иконка чипа0
    Иконка глаза707
    Иконка комментариев0
    Иконка чипа+1