Частичные перевод статьи “How to make your code faster using JavaScript Sets” с сайта medium.com
Я уверен, что большинство разработчиков привыкли использовать базовые типы в JavaScript: number, string, object, array, boolean.
Для большинства случаев этого вполне достаточно. Но если вы хотите сделать вам код максимально быстрым и масштабируемым – базовых типов может не хватить.
В этой статье мы поговорим как JavaScript Sets могут сделать ваш код быстрее, особенно если растет кодовая база. Есть много общего между Коллекциями и Массивами. Но использование коллекций часто придает скорости, чего невозможно достичь с Массивами.
В чем разница
Самое важное отличие Коллекций от Массивов в том, что массив это индексированная коллекция. Иными словами элементы массива отсортированы по их индексам.
С другой же стороны, коллекции не имеют индексов. Их элементы итерируемы в порядке их добавления и обязаны быть уникальными.
В чем преимущества
В прямом сравнении коллекции имеют несколько преимуществ на массивами, особенно если говорить о скорости выполнения:
- Поиск элементов.
indexOf
илиincludes
работают сравнительно медленно; - Удаление элементов. Из коллекций элементы удаляются по значению. Это на много быстрее, чем использование
splice
, например; - Вставка элементов. Быстрее добавить элемент в коллекцию, чем делать это в массив через
push
,unshift
и тп.; - Удаление дубликатов. Тут даже делать ничего не надо – все элементы уже уникальны.
Есть еще одна особенность, которая может пригодиться (но это не точно). В коллекции можно хранить и искать значение NaN
.
Сложность выполнения
Методы для поиска элементов массива имеют линейную сложность выполнения O(N)
. Это значит сложность растет по мере роста количества элементов.
У коллекций же основные методы имеют сложность O(1)
– размер коллекции никак не влияет на скорость выполнения.
Примеры
Создание объекта коллекции
var set = new Set();
Операции с элементами
set.add(1); // Set { 1 } set.add(2); // Set { 1, 2 } set.add(1); // Set { 1, 2 } set.add({a: 1}) // Set { 1, 2, {a: 1} } // Литералы объектов уникальны. Удалить по значению нельзя. set.add({a: 1}); // Set { 1, 2, {a: 1}, {a: 1} } set.delete({a: 1}); // false console.log(set); // Set { 1, 2, {a: 1}, {a: 1} } // Удалять нужно по ссылке var o = {a: 1}; set.add(o); // Set { 1, 2, {a: 1}, {a: 1}, {a: 1} } set.delete(o); // true console.log(set); // Set { 1, 2, {a: 1}, {a: 1} } set.has(1); // true set.has(3); // false set.has({a: 1}); // false set.size; // 4
Другие примеры работы с коллекциями
// выведет элементы по порядку: 1, "some text", {"a": 1, "b": 2} for (let item of mySet) console.log(item); // выведет элементы по порядку: 1, "some text", {"a": 1, "b": 2} for (let item of mySet.keys()) console.log(item); // выведет элементы по порядку: 1, "some text", {"a": 1, "b": 2} for (let item of mySet.values()) console.log(item); // выведет элементы по порядку: 1, "some text", {"a": 1, "b": 2} //(key и value в данном случае одинаковы) for (let [key, value] of mySet.entries()) console.log(key); // преобразует Set в Array var myArr = Array.from(mySet); // [1, "some text", {"a": 1, "b": 2}] // следующее будет работать при запуске с HTML документом mySet.add(document.body); mySet.has(document.querySelector("body")); // true // преобразования из Array в Set и обратно mySet2 = new Set([1,2,3,4]); mySet2.size; // 4 [...mySet2]; // [1,2,3,4] // пересечение можно представить следующим образом var intersection = new Set([...set1].filter(x => set2.has(x))); // разность можно представить следующим образом var difference = new Set([...set1].filter(x => !set2.has(x))); // Обход элементов set при помощи forEach mySet.forEach(function(value) { console.log(value); }); // 1 // 2 // 3 // 4
var myArray = ["value1", "value2", "value3"]; // Используйте конструктор Set для преобразования Array в Set var mySet = new Set(myArray); mySet.has("value1"); // вернёт true // Используйте spread оператор для преобразования Set в Array console.log([...mySet]); // Отобразит тот же массив, что и myArray
var text = 'India'; var mySet = new Set(text); // Set ['I', 'n', 'd', 'i', 'a'] mySet.size; // 5
На этом все. Если вы еще не работали с коллекциями – надеюсь я продемонстрировал насколько они могут быть полезны.