Массивы и коллекции
Массив в JavaScript — это объект с числовыми ключами и особым свойством length, а не непрерывный блок памяти, как в C. Отсюда две вещи, вокруг которых крутятся вопросы на собеседовании — массив можно сделать разреженным (с дырами), и почти каждый метод либо меняет массив на месте, либо возвращает новый, и путать эти два класса нельзя.
Поверх массива язык даёт четыре ключевые коллекции — Map и Set с их слабыми вариантами WeakMap/WeakSet — и типизированные массивы для сырых байтов. Каждая решает задачу, которую обычный объект или массив решают плохо — ключи-объекты, уникальность, привязка метаданных без утечек памяти, бинарные данные. Полная карта — в слоях ниже.
Карта темы
- Методы массивов —
map,filter,reduce,forEach— что каждый возвращает и для чего он. - Перебирающие методы —
some,every,find,findIndexи их короткое замыкание. - Мутация массива — методы, меняющие массив на месте, против возвращающих новый;
sliceпротивsplice. - Сортировка — лексикографический порядок по умолчанию, компаратор, стабильность и дыры.
- Разреженные массивы — плотные против разреженных, дыры и почему методы их пропускают.
- Типизированные массивы —
ArrayBufferкак сырые байты и представления вродеUint8Array. - Коллекция Map — ключи любого типа, порядок вставки и отличие от объекта и
Set. - Коллекция Set — уникальные значения,
SameValueZeroи дедупликация. - Слабые коллекции —
WeakMap/WeakSet, слабые ссылки и сборка мусора.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Использовать forEach там, где нужен результат | forEach возвращает undefined; собрать массив можно только через map |
Считать, что sort() сортирует числа | По умолчанию сортировка лексикографическая — [1, 10, 2], нужен компаратор (a, b) => a - b |
Забыть, что sort, reverse, splice мутируют | Исходный массив меняется на месте — сначала копируйте [...arr] |
Путать slice и splice | slice копирует и не трогает исходник; splice вырезает из исходника |
Ждать, что map обойдёт дыры | Дыры пропускаются, и map сохраняет их в результате |
| Использовать объект как словарь с ключами-объектами | Ключи объекта — только строки/символы; для ключей-объектов нужен Map |
Ждать, что WeakMap итерируется или имеет size | Слабые ссылки могут исчезнуть в любой момент — перебор невозможен |
Значение для собеседований
Массивы и коллекции спрашивают как проверку того, различаете ли вы мутацию и копию, значение и ссылку, а также знаете ли, какая коллекция под какую задачу заточена. Кандидат, который на вопрос «как убрать дубликаты» отвечает [...new Set(arr)] и добавляет про SameValueZero, сразу выглядит сильнее.
Что обычно проверяют:
- Какие методы возвращают новый массив, а какие мутируют исходный, и что они возвращают.
- Как правильно отсортировать числа и почему
sortбез компаратора ошибается. - Чем
Mapотличается от объекта и отSet, когда что выбирать. - Зачем нужны
WeakMap/WeakSetи как они связаны со сборкой мусора.
Типичный неверный ответ: «map и forEach — одно и то же» или «sort() сам разберётся с числами». На деле forEach ничего не возвращает, а sort без компаратора сравнивает строки код-юнитов.