> Как пройтись по всем элементам массива в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Avito, Яндекс

Стек: JavaScript

> Пример ответа

Короткий ответ

В JavaScript есть несколько способов обойти массив: for, for...of, forEach, map, filter, reduce и другие. Выбор зависит от задачи: for даёт полный контроль, for...of удобен для итерации, forEach - для side effects, map - для трансформации, filter - для фильтрации, reduce - для агрегации. Для асинхронных операций лучше for...of с await или Promise.all.

Подробное объяснение

Все способы обхода массива в JavaScript делятся на три категории: классические циклы, методы с колбэками и итераторы.

Классические циклы:

  • for (let i = 0; i < arr.length; i++) - максимальный контроль, доступ к индексу, можно прервать через break или continue
  • for...of - ES6, работает с любыми iterables, удобен для чтения, можно прервать
  • for...in - не рекомендуется для массивов, так как перечисляет ключи (включая унаследованные)

Методы массива с колбэками (все принимают (element, index, array)):

  • forEach - выполняет функцию для каждого элемента, не возвращает новый массив, не поддерживает break
  • map - создаёт новый массив из результатов вызова функции
  • filter - возвращает новый массив с элементами, прошедшими проверку
  • reduce - свёртка массива в одно значение
  • some/every - проверяют условие, возвращают boolean
  • find/findIndex - ищут первый подходящий элемент или его индекс

Итераторы:

  • Array.prototype[Symbol.iterator] - позволяет использовать for...of
  • arr.entries(), arr.keys(), arr.values() - возвращают итераторы для пар [index, value], индексов или значений

Для асинхронного обхода:

  • for...of с await - последовательное выполнение
  • Promise.all(arr.map(async fn)) - параллельное выполнение

На практике

Выбор способа обхода диктуется задачей и контекстом:

  • Для простого перебора с side effects (логирование, запись в DOM) - forEach
  • Для трансформации данных - map
  • Для фильтрации - filter
  • Для вычисления суммы или другого агрегата - reduce
  • Для раннего выхода из цикла - for или for...of с break
  • Для асинхронных операций с ожиданием каждого - for...of с await
  • Для параллельных асинхронных операций - Promise.all с map

Важно помнить про производительность: классический for быстрее методов с колбэками на больших массивах (10⁵+ элементов), но разница редко критична. Методы с колбэками создают новый контекст вызова для каждой итерации, что может быть overhead.

Пример кода

JAVASCRIPT
// Классический for
const arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
// for...of
for (const item of arr) {
console.log(item);
}
// forEach
arr.forEach(item => console.log(item));
// map - трансформация
const doubled = arr.map(x => x * 2);
// filter - фильтрация
const evens = arr.filter(x => x % 2 === 0);
// reduce - сумма
const sum = arr.reduce((acc, x) => acc + x, 0);
// Асинхронный обход последовательно
async function processSequentially(items) {
for (const item of items) {
await asyncOperation(item);
}
}
// Асинхронный обход параллельно
async function processParallel(items) {
await Promise.all(items.map(item => asyncOperation(item)));
}

Как отвечать на собеседовании

Начни с перечисления основных способов, затем уточни, что выбор зависит от задачи. Покажи понимание trade-off между производительностью, читаемостью и функциональностью. Упомяни, что for...in не подходит для массивов. Добавь про асинхронный обход - это отличает senior от junior. Если спросят про производительность, скажи, что для большинства задач разница несущественна, но для критичных участков можно использовать for.

Что проверяет интервьюер

  • Знание базовых и продвинутых методов обхода
  • Понимание разницы между императивным и декларативным подходом
  • Умение выбирать правильный инструмент под задачу
  • Понимание работы event loop и асинхронности в контексте обхода
  • Осведомлённость о производительности и памяти

Типичные ошибки

  • Использование for...in для массивов - перебирает ключи, включая прототипные
  • Попытка прервать forEach через return - не работает, нужно использовать for или some/every
  • Забывание про side effects в map - если не нужен новый массив, используй forEach
  • Неправильное использование await внутри forEach - forEach не ждёт промисы, нужен for...of
  • Мутация исходного массива в map/filter - эти методы должны быть чистыми
  • Избыточное создание промежуточных массивов при цепочке методов - для больших данных лучше использовать reduce или for

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью