Найти тему
stas-webdev

Как использование JavaScript Maps может сделать ваш код быстрее

Оглавление

Среди положительных моментов, появившихся в JavaScript с приходом ES6, мы увидели новые типы данных - наборы (Set) и карты (Map). В отличие от обычных объектов и массивов, это «коллекции ключей». Это означает, что их поведение несколько отличается и, при правильном использовании, они дают значительные преимущества в производительности.

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

Чем Map отличается от Object?

Существует два основных различия между картами и обычными объектами JavaScript.

1. Любые значения в качестве ключей

Каждый ключ в обычном объекте JavaScript должен быть либо строкой, либо символом. Пример ниже демонстрирует это:

В отличие от простых объектов, карты позволяют вам использовать в качестве ключей функции, объекты и любые другие типы примитивов (включая NaN) - как показано ниже:

Эта способность обеспечивает большую гибкость при связывании разных типов данных.

2. Прямая итерация

Чтобы перебрать ключи, значения или записи в объекте, вы должны либо преобразовать их в массив, используя такой метод, как Object.keys (), Object.values () или Object.entries (), либо использовать for ... в цикле. Поскольку объекты не могут быть непосредственно итерируемыми, цикл for ... in имеет несколько ограничений: он выполняет итерацию только по перечисляемым, не символьным свойствам и делает это в произвольном порядке.

Но объекты Map позволяют итерировать их напрямую, и, поскольку они представляют собой набор ключей, порядок итерации такой же, как и порядок вставки. Чтобы перебрать записи Map, вы можете использовать цикл for ... of или метод forEach. Следующий код показывает оба перечисленных способа:

Чтобы узнать количество записей в объекте, вы должны сначала преобразовать его в массив следующим образом: Object.keys ({}). length. Напротив, объекты Map имеют свойство size, обратившись к которому вы всегда можете получить количество записей в карте.

Чем Map отличается от Set?

Карты ведут себя очень похоже на наборы, и они используют несколько одинаковых методов, включая has, get, delete и size. Оба являются коллекциями ключей, что означает, что вы можете использовать такие методы, как forEach, для перебора элементов в порядке вставки.

Основное отличие состоит в том, что карта состоит из двух измерений с элементами, которые входят в пару ключ / значение. Так же, как вы можете преобразовать массив в набор, вы можете преобразовать 2D-массив в карту:

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

Чтобы переключить карту обратно в массив, вы можете использовать синтаксис деструктурирования ES6:

До недавнего времени преобразовывать карту в объект было не так удобно (и наоборот), и вам нужно было использовать функцию, подобную приведенной ниже:

Но теперь, с выходом ES2019 , мы получили два новых методов объекта - Object.entries () и Object.fromEntries () - которые делают это намного проще:

Однако, прежде чем использовать Object.fromEntries для преобразования карты в объект, убедитесь, что ключи карты дают уникальные результаты при преобразовании в строку. В противном случае вы рискуете потерять данные при конвертации.

Тесты производительности

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

Я использовал console.time () для тестирования, поэтому результаты, что приведены ниже, будут зависеть от моей системы и версии Node.js, однако мои результаты постоянно показывают увеличение производительности при использовании Map, особенно при добавлении и удалении записей.

Поиск записей

Object: 0.250ms

Map: 0.095ms (в 2.6 раза быстрее)

Добавление записей

Object: 0.229ms

Map: 0.005ms (в 45.8 раз быстрее!)

Удаление записей

Object: 0.376ms

Map: 0.012ms (в 31 раз быстрее!)

В каких случаях карты медленнее

В моих тестах я обнаружил один случай, когда простые объекты превзошли Map: при использовании цикла for для создания нашего исходного объекта и карты. Этот результат удивителен, поскольку без цикла for добавление записей на карту происходит быстрее добавления записей к стандартному объекту.

Object: 32.143ms

Map: 163.828ms (в 5 раз медленнее)

Пример использования

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

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

Здесь карты предпочтительнее объектов, потому что нам нужно динамически добавлять и удалять значения и потому что мы заранее не знаем форму данных (или количество записей).

Я надеюсь, что вы эта статья была полезной для вас, и, если вы раньше не сталкивались с JS Map, она открыла вам глаза на ценную часть современного JavaScript.

Пишите в комментариях свои примеры использования объектов Map в JavaScript.

Перевод статьи How JavaScript Maps Can Make Your Code Faster