Массивы в JavaScript: руководство и примеры

Быстрые ссылки
Объявление массива
Доступ к элементам
Добавление элементов
Удаление элементов
Перебор массива
Преобразование с map
Фильтрация
Утилиты и часто используемые методы
Практические рекомендации и чек‑листы
Введение
Массивы в JavaScript — это объектоподобная структура данных, предназначенная для хранения упорядоченных наборов значений. В отличие от массивов в языках со статической типизацией, здесь элементы могут быть разных типов, размер массива может меняться динамически, а язык предоставляет мощный набор методов для преобразования и обработки данных.
Определение: массив — упорядоченная последовательность значений, индексируемая целыми числами, начиная с 0.
Важно: индекс всегда целое число >= 0; если нужен ассоциативный ключ — используйте объект или Map.
Объявление массива
Вы создаёте массив с помощью квадратных скобок или конструктора Array. Предпочтительнее литерал массива ([]) — он короче и безопаснее.
let emptyArray = [];
let filledArray = ['hello', 123, { foo: 'bar' }, ['x', 'y']];Факты:
- Массивы не имеют фиксированного типа элементов.
- Длина массива хранится в свойстве length; при добавлении/удалении она автоматически обновляется.
Доступ к элементам
Элемент получают по индексу в квадратных скобках. Индексация начинается с 0.
let myArray = ['foo', 'bar', 'example'];
console.log(myArray[1]); // 'bar'Если индекс выходит за пределы, вернётся undefined. Чтобы изменить элемент — просто присвойте новое значение по индексу:
myArray[1] = 'test';
// myArray теперь ['foo', 'test', 'example']Совет: избегайте использования нецелых или отрицательных индексов — массивы в JS их не поддерживают.
Добавление элементов
Основные методы:
- push(item) — добавляет в конец;
- unshift(item) — добавляет в начало (сдвигает все индексы — медленнее для длинных массивов);
- splice(index, deleteCount, …items) — вставка/удаление в середине;
- spread (…) и concat() — создают новый массив.
Примеры:
let arr = ['car', 'truck'];
arr.push('bus'); // ['car', 'truck', 'bus']
let arr2 = ['car', 'truck'];
arr2.unshift('bus'); // ['bus', 'car', 'truck']
let arr3 = ['car', 'truck'];
arr3.splice(1, 0, 'bus'); // ['car', 'bus', 'truck']
// без мутаций — с spread
let joined = ['a', 'b', 'c', ...['x', 'y', 'z']];Важно: push/unshift/splice изменяют исходный массив (мутабельные операции). Если нужно иммутабельное поведение — используйте spread/concat и возвращайте новый массив.
Удаление элементов
Основные методы:
- pop() — удаляет последний элемент и возвращает его;
- shift() — удаляет первый элемент и возвращает его (медленнее на больших массивах);
- splice(index, count) — удаляет count элементов, начиная с index;
- filter() — возвращает новый массив без нежелательных элементов (не мутирует исходный);
- delete arr[index] — удаляет значение, но оставляет “пустой” слот (не рекомендуется).
Примеры:
['car','truck','bus'].pop(); // ['car','truck']
['car','truck','bus'].shift(); // ['truck','bus']
const arr = ['car','truck','bus'];
arr.splice(arr.indexOf('truck'), 1); // ['car','bus']
// иммутабельный подход
const filtered = ['car','truck','bus'].filter(v => v !== 'truck'); // ['car','bus']Важно: indexOf возвращает -1, если значение не найдено — проверяйте это перед передачей в splice.
Перебор массива
Есть несколько способов перебрать массив. Выбор зависит от цели — нужен ли индекс, можно ли прервать цикл, нужно ли собрать результат.
- for — классический, можно прерывать через break/return (в функции):
const arr = ['car','truck','bus'];
for (let i = 0; i < arr.length; i++) {
console.log(`Vehicle at position ${i} is ${arr[i]}`);
}- forEach — удобен для побочных эффектов, нельзя прервать (return затрагивает только callback):
['car','truck','bus'].forEach((vehicle, i) => {
console.log(`Vehicle at position ${i} is ${vehicle}`);
});- for…of — читабельный, можно использовать break:
for (const [i, vehicle] of Array.from(arr).entries()) {
console.log(i, vehicle);
}- for…in — перебирает перечисляемые свойства (не используйте для массивов).
Совет: используйте forEach/map/filter если хотите декларативности; for/for…of — если нужен контроль над потоком.
Преобразование: map
map(callback) пробегает по массиву и возвращает новый массив из результатов вызова callback.
const numbers = [2, 4, 8, 16];
const squares = numbers.map(v => v * v); // [4, 16, 64, 256]Callback получает три аргумента: (value, index, array). Map не мутирует исходный массив.
Применение: форматирование данных для UI, создание новых структур, проекция полей объектов.
Фильтрация: filter
filter(callback) возвращает новый массив с элементами, для которых callback вернул true.
const evens = [1,2,3,4].filter(v => v % 2 === 0); // [2,4]filter полезен для удаления нежелательных элементов, выделения подмножеств и подготовки данных для дальнейшей обработки.
Полезные утильные методы
Короткая шпаргалка по часто используемым методам:
concat(): объединяет массивы и возвращает новый массив.
Пример: [‘a’,’b’,’c’].concat([‘x’,’y’,’z’]) => [‘a’,’b’,’c’,’x’,’y’,’z’]
join(separator): объединяет значения в строку.
Пример: [‘a’,’b’,’c’].join(‘ - ‘) => ‘a - b - c’
indexOf(value): индекс первого совпадения или -1.
lastIndexOf(value): индекс последнего совпадения.
includes(value): true, если значение присутствует.
new Array(n): создаёт массив длины n с undefined в слоты (будьте осторожны с map на таком массиве — нужно заполнять сначала).
every(callback): true, если callback вернёт true для всех элементов.
some(callback): true, если callback вернёт true для хотя бы одного элемента.
find(callback): возвращает первый элемент, удовлетворяющий условию, или undefined.
findIndex(callback): индекс первого совпадения.
reduce(callback, initialValue): аккумулирует значение по всему массиву — универсальный инструмент для сумм/агрегаций.
Пример reduce для суммы:
const sum = [1,2,3,4].reduce((acc, v) => acc + v, 0); // 10Производительность и мутабельность
- Методы push/pop работают быстро для конца массива;
- unshift/shift и splice для середины/начала могут быть медленнее, так как требуется сдвиг элементов;
- создание новых массивов (spread, concat, filter, map) полезно для иммутабельности, но создаёт дополнительные аллокации;
- для большого объёма данных выбирайте подходы, минимизирующие копирование.
Распространённые ошибки и когда массивы не подходят
- Использовать массив как объект с ключами строкового типа: если нужны ассоциативные ключи — используйте Object или Map.
- Ожидать порядок элементов при параллельной/асинхронной модификации — синхронизируйте доступ.
- Полагаться на sparse-массивы (пропущенные индексы) — это источник неожиданных undefined и проблем с итераторами.
- Хранить очень большие данные в массиве без учёта памяти — для потоковой обработки лучше подходы на базе генераторов/стримов.
Альтернативные структуры и подходы
- Object и Map — для пар ключ/значение;
- Set — для множества уникальных значений;
- TypedArray (Int8Array, Uint8Array и т.д.) — для эффективно реализованных однотипных массивов (низкоуровневые операции и работа с бинарными данными);
- Linked list / Deque — когда требуется частое добавление/удаление в середине (в JS стандартной реализации нет, но можно реализовать вручную).
Ментальные модели и эвристики
- Массив = упорядоченная лента: индексы — это позиции на ленте.
- Операции “в конце” cheap, “в начале/середине” — potentially expensive.
- Предпочитайте декларативные методы (map/filter/reduce) для простоты и читабельности. Если нужен контроль — используйте for/for…of.
Чек‑лист для разработчика
Для автора кода:
- Проверил ли я, что индекс существует перед доступом?
- Мутирую ли я массив? Нужен ли иммутабельный подход?
- Не использую ли я массив как объект?
- Есть ли более подходящая структура (Map/Set/TypedArray)?
Для ревьювера:
- Понятна ли контрактная часть (вход/выход функций с массивами)?
- Были ли учтены крайние случаи (пустой массив, undefined, дубликаты)?
- Производительность: не создаются ли лишние копии в горячем цикле?
Мини‑методика: как выбрать метод
- Нужно ли возвращать новый массив с преобразованием? -> map
- Нужно ли отфильтровать элементы? -> filter
- Нужен ли простой перебор для побочных эффектов? -> forEach или for
- Нужна ли агрегация/свертка? -> reduce
- Нужны ли уникальные значения? -> Set
Критерии приёмки
- Функция корректно обрабатывает пустой массив;
- Исходный массив не изменяется, если это указано в контракте (проверить тестами);
- Производительность в пределах ожиданий для заданного объёма данных (критические методы покрыты);
- Нет использования delete для удаления элементов; вместо этого — splice/filter/pop/shift.
Тестовые случаи / Приёмочные сценарии
- Пустой массив -> ожидаемый результат (например, [] или 0).
- Массив с одним элементом -> ожидаемый результат.
- Дубликаты в массиве -> поведение при indexOf/find.
- Значения undefined/null внутри массива -> корректная обработка.
- Очень длинный массив -> не превышает допустимое время выполнения для критических функций.
Примеры шаблонов и сниппетов
Глубокое клонирование массива объектов (наиболее простой способ, не для функций):
const deepClone = arr => JSON.parse(JSON.stringify(arr));Удаление элемента по значению без мутации:
const removeValue = (arr, value) => arr.filter(v => v !== value);Уникальные значения:
const unique = arr => Array.from(new Set(arr));Группировка по ключу (reduce):
const groupBy = (arr, key) => arr.reduce((acc, item) => {
const k = item[key];
(acc[k] = acc[k] || []).push(item);
return acc;
}, {});Безопасность и приватность
Массивы сами по себе не создают уязвимостей, но при работе с данными пользователя следите за следующими моментами:
- Не отправляйте необработанные данные в клиент без проверки;
- При сериализации/десериализации следите за размерам данных и таймаутами;
- При работе с бинарными массивами используйте TypedArray для предсказуемого поведения и меньших накладных расходов.
Часто задаваемые вопросы
Чем отличается map от forEach?
map возвращает новый массив с результатами функции; forEach используется для побочных эффектов и возвращает undefined.
Как удалить все элементы массива?
arr.length = 0; // очищает массив на месте // или arr = []; // создаёт новый пустой массив (если нужно восстановить ссылку — используйте length = 0)
Когда использовать Set вместо массива?
Когда нужна коллекция уникальных значений и частые операции проверки наличия (has) — Set быстрее и семантически точнее.
Заключение
Массивы в JavaScript — гибкий и удобный инструмент для большинства задач по работе с упорядоченными данными. Знание ключевых методов (map, filter, reduce, forEach) и понимание последствий мутаций помогут писать более надёжный, читаемый и производительный код. Выбирайте структуру данных в зависимости от требований к уникальности, скорости доступа и характера операций.
Короткая сводка (Key facts)
- Индексация с 0; длина хранится в length;
- Операции в конце массива быстрее, чем в начале/середине;
- map/filter/reduce возвращают новые массивы (не мутируют исходный);
- Для ассоциативных пар — используйте Object/Map; для уникальных множеств — Set.
Часто задаваемые вопросы ниже также доступны в машинно‑читаемом формате JSON‑LD в разделе метаданных.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента