> Как работает callback в методе map в JavaScript и что означают его аргументы (JavaScript)

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

Компании: Иннотех, Дом.рф

Стек: JavaScript

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

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

map вызывает callback для каждого элемента массива и возвращает новый массив из результатов. Callback принимает три аргумента: currentValue (текущий элемент), index (позиция в массиве) и array (исходный массив). Важно: map не мутирует исходный массив, пропускает пустые слоты и всегда возвращает массив той же длины.

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

Метод map - это иммутабельная операция над массивом, реализованная через внутренний цикл. Callback выполняется последовательно для каждого элемента, кроме пропусков в sparse arrays. Три аргумента callback:

  • currentValue - значение элемента на текущей итерации. Это единственный обязательный аргумент.
  • index - числовой индекс элемента (0-based). Полезен для доступа к соседним элементам или генерации идентификаторов.
  • array - ссылка на исходный массив, к которому был вызван map. Используется редко, но нужен, например, для проверки длины или доступа к другим элементам без замыкания.

map гарантирует, что callback не будет вызван для элементов, добавленных после начала итерации, и для удалённых элементов. Порядок вызова соответствует порядку индексов от 0 до length-1.

На практике

В продакшене map чаще всего используют с одним аргументом - currentValue. Второй аргумент (index) применяют для рендеринга списков с ключами в React или для нумерации. Третий аргумент (array) нужен в редких случаях, например, при трансформации на основе соседних элементов или проверке, является ли элемент последним.

Важно помнить про thisArg - второй параметр map, который задаёт контекст this внутри callback. Это альтернатива стрелочным функциям, но на практике предпочитают стрелки или .bind().

Пример кода

JAVASCRIPT
const numbers = [1, 2, 3, 4];
// Только currentValue
const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8]
// С index для генерации строк
const labeled = numbers.map((n, i) => `Item ${i + 1}: ${n}`);
// ["Item 1: 1", "Item 2: 2", "Item 3: 3", "Item 4: 4"]
// С array для проверки последнего элемента
const withComma = numbers.map((n, i, arr) =>
i === arr.length - 1 ? n : n + ','
); // ["1,", "2,", "3,", 4]
// Использование thisArg
const multiplier = { factor: 10 };
const scaled = numbers.map(function(n) {
return n * this.factor;
}, multiplier); // [10, 20, 30, 40]

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

Начни с определения: map создаёт новый массив, применяя callback к каждому элементу. Затем перечисли три аргумента callback с примерами использования. Подчеркни иммутабельность и отличие от forEach (возвращает новый массив, а не undefined). Упомяни, что map не вызывает callback для пустых слотов, но сохраняет их в новом массиве как empty. Для уровня senior добавь про внутреннюю реализацию: map - это итеративный протокол, который нельзя прервать (в отличие от reduce с условием). Упомяни полифилл для старых браузеров.

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

  • Понимание функционального программирования: иммутабельность, чистота функций.
  • Знание спецификации ECMAScript: поведение с sparse arrays, порядок итерации, влияние мутаций массива внутри callback.
  • Умение выбирать правильный метод: map vs forEach vs reduce vs flatMap.
  • Глубина: знание thisArg, отличие от Array.from с mapFn, работа с TypedArrays.

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

  • Использование map для побочных эффектов (нужен forEach).
  • Забывание вернуть значение из callback - получается массив из undefined.
  • Предположение, что map мутирует исходный массив.
  • Игнорирование sparse arrays: [1, , 3].map(x => x * 2) вернёт [2, empty, 6].
  • Передача асинхронного callback без обработки промисов - map не ждёт resolve.

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

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