Предупреждение, спойлер: возможно.

JavaScript Наборы и Карты существуют уже несколько лет, но я все еще получаю много вопросов о них. Мои студенты задаются вопросом, следует ли им заменять традиционные объекты и массивы этими новыми типами данных. Хотя есть некоторые убийственные варианты использования наборов и карт, вам действительно следует смотреть на них как на специализированные инструменты, а не как на швейцарские армейские ножи.

Когда использовать наборы

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

const mySet = new Set();

mySet.add(1); // add item 
mySet.add('a');
mySet.size; // 2 
mySet.delete(1)
mySet.has(1); // false
mySet.clear(); // empties set 

Вам нужно удалить дубликаты

Это, наверное, единственный раз, когда я действительно видел, как наборы используются в дикой природе. Это удобный лайнер:

const arr = [1,2,3,4,4,5,6,7,7,7]
const unique = [...new Set(arr)]
// unique equals [1,2,3,4,5,6,7]

Вы выполняете задачи алгоритма

Если вы используете что-то с установленными проблемами, очевидно, что вам подойдут наборы. Вы можете увидеть в документации по набору, как реализовать основные действия набора. Этот материал, вероятно, возникнет при выполнении задач алгоритма, поэтому стоит взглянуть.

Когда использовать карты

Maps, честно говоря, я думал, что они захватят все, но потом, когда вы дошли до этого: они не так уж важны, как вы могли подумать. Это еще один способ хранения данных типа "ключ-значение", но они более целенаправленны, чем объекты, поэтому имеют некоторые дополнительные преимущества. Вот ускоренный курс (документы карты):

const myMap = new Map();
myMap.set('a', 1);
myMap.set('b', 2);
myMap.set('c', 3);
myMap.get('a'); // 1
myMap.set('a', 'ok');
myMap.get('a'); // 'ok'
myMap.size; // 3
myMap.delete('b'); // removes b key/value
myMap.clear() // empties map

Вам нужны нестроковые ключи

Это наиболее очевидное преимущество карт, они могут использовать практически все что угодно. Объекты будут всегда преобразовывать в строку все, что используется в качестве ключа. Например, если вы попытаетесь использовать уникальные объекты в качестве самих ключей объектов, все они будут преобразованы в '[Object object]' и перезапишут друг друга. К счастью, с картами это не проблема! Каждый объект отлично работает как уникальный ключ. И если вы использовали тот же ключ объекта с новым значением, оно перезапишет исходное значение, как и следовало ожидать. Это не очень распространенный сценарий, но его полезно знать.

Вы заботитесь о порядке размещения

Технически объекты вроде поддерживают порядок вставки с современным JS. ОДНАКО, похоже, есть некоторые предостережения для поддержания порядка ключей. Если вам действительно нужно быть уверенным, что ваши пары ключ / значение сохраняют порядок итераций, используйте карту.

У вас действительно огромный набор данных

Это зависит от браузера, но для браузеров Chrome Карты могут содержать 16 миллионов записей, в то время как объекты могут содержать только 11 миллионов. Так что ... это технически вещь, я просто сомневаюсь, что вы когда-нибудь попадете в нее (если вы это сделаете, пожалуйста, скажите мне, какие данные вы спорили).

Вот и все!

Если вы думали, что это довольно специфические ситуации, вы были бы правы. Могу поспорить, что есть крайние случаи, которые я пропустил (пожалуйста, опубликуйте ниже, если вы знаете о них), но эти ситуации выше - хорошие вещи. Это означает, что вы можете продолжать использовать обычные объекты подавляющее большую часть времени. Если вы действительно хотите использовать карты и наборы для удобства чтения или чего-то в этом роде, дерзайте. Просто не думайте, что вы что-то упускаете, если не упускаете.

Другие ошибки

JSON пока не может правильно кодировать карты и наборы, так что это то, что вы можете подумать, если имеете дело с API. Сначала вам нужно преобразовать каждую карту или вернуть ее в простой старый объект JS. Я уверен, что это изменится в будущем.

Также вы можете услышать, что некоторые люди говорят, что Карты того стоят, потому что по умолчанию они являются итеративными. Однако, поскольку мы уже используем синтаксис ES2015 + для получения карт, у нас также будут итерационные функции Object.keys, values и entries. Что вроде как немного украдет этот гром. И, насколько мне известно, у карт нет бонуса к скорости итерации. Это подводит меня к моему последнему пункту.

Разве карты и наборы не быстрее?

…Может быть? На странице карт MDN написано, что они «лучше работают в сценариях, включающих частое добавление и удаление пар ключ-значение». Однако я лично не видел этого в моих тестах или исследованиях. Это правда, что функция Map.delete быстрее, чем ключевое слово object delete, но здесь есть одна загвоздка. Функция Map.set работает медленнее, чем метод set внутреннего объекта, поэтому любой бонус, который вы можете получить от более быстрого удаления, получит огромный кусок, вынутый более медленными вставками. Кроме того, некоторые браузеры реализуют разные функции по-разному, а это означает, что это не постоянный рост. В моем, хотя и ограниченном, тестировании я обнаружил, что объекты всегда были быстрее, но ненамного.

Что касается наборов, не может быть никаких сомнений в том, что set.has быстрее, чем array.includes (это O (N) для массивов по сравнению с O (1) для наборов). К сожалению, set.add кажется намного медленнее, чем arr.push. Итак, если бы список был достаточно большим, а поиск был дорогостоящим, процесс создания набора в первую очередь был бы настолько медленным, что любое увеличение скорости от повторного поиска было бы потеряно. Я думаю, что если вы сотни или тысячи раз искали в списке с тонной позиций, то наборы могут того стоить. Но я бы порекомендовал проверить производительность перед заменой.

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

Окончательный вердикт

Разработчики JS ОБОЖАЮТ блестящие новые вещи, но, за исключением этих специализированных случаев использования, нет особой причины использовать новые типы данных. Это новые инструменты, которые нужно добавить в свой набор инструментов, а не замену.

счастливого кодирования всех,

Майк