</> Praktum

Главная / JavaScript / Array.map()

Справочник · JavaScript

Array.map(): преобразуем каждый элемент

Редакция PraktumОбновлено 6 мин чтенияУровень: новичок

Метод map() вызывает функцию для каждого элемента массива и собирает её результаты в новый массив той же длины. Исходный массив не меняется. map нужен, когда каждому элементу соответствует один результат: цены со скидкой, строки для вывода, объекты нужного вида.

Коротко
  • arr.map((item) => новоеЗначение) — новый массив той же длины.
  • Исходный массив не меняется.
  • В функции с фигурными скобками нужен return.
  • Объект из стрелки возвращают в круглых скобках: (x) => ({ … }).
  • Результат не нужен — используй forEach или for...of, а не map.

Минимальный пример

const prices = [100, 250, 400];
const withTax = prices.map((price) => price * 1.2);

console.log(withTax); // [120, 300, 480]
console.log(prices);  // [100, 250, 400] — не изменился

Функция получает каждую цену и возвращает новую. Возвращённые значения по порядку становятся элементами нового массива.

Синтаксис и параметры

const result = array.map(callback(element, index, array), thisArg);
Параметры map()
ПараметрЧто это
elementтекущий элемент
indexего индекс, необязательный
arrayсам массив, необязательный
thisArgthis для обычной функции; со стрелкой не нужен
Возвращаетновый массив той же длины

Преобразование объектов

const lessons = [
  { title: 'HTML', minutes: 15 },
  { title: 'CSS', minutes: 20 },
];

const titles = lessons.map((lesson) => lesson.title);          // ['HTML', 'CSS']
const cards = lessons.map((lesson, index) => ({
  ...lesson,
  number: index + 1,
  label: `${lesson.title} · ${lesson.minutes} мин`,
}));

Чтобы стрелочная функция вернула объект без return, его оборачивают в круглые скобки: (x) => ({ … }). Без скобок фигурные скобки считаются телом функции, и вернётся undefined. Не меняй исходные объекты внутри map — создавай новые через spread, иначе изменения «протекут» в исходный массив.

Вывод списка на страницу

const list = document.querySelector('.lessons');

list.replaceChildren(
  ...lessons.map((lesson) => {
    const li = document.createElement('li');
    li.textContent = lesson.title;
    return li;
  })
);

map превращает массив данных в массив элементов, которые сразу добавляются на страницу. В React так выводят списки: {items.map((item) => <li key={item.id}>…</li>)}. Текст вставляй через textContent: строковая склейка HTML с данными пользователя опасна.

Цепочки: filter, map, sort

const names = users
  .filter((u) => u.isActive)
  .map((u) => u.name)
  .sort((a, b) => a.localeCompare(b, 'ru'));

Каждый метод возвращает новый массив, поэтому их удобно сцеплять. Сначала filter отбирает, потом map преобразует. Если нужно и отфильтровать, и преобразовать одним проходом, есть flatMap: вернул пустой массив — элемент пропущен.

Ловушка: map(parseInt)

['1', '2', '3'].map(parseInt);   // [1, NaN, NaN] — сюрприз
['1', '2', '3'].map(Number);     // [1, 2, 3]
['1', '2', '3'].map((s) => parseInt(s, 10)); // [1, 2, 3]

map передаёт в функцию три аргумента: элемент, индекс и массив. parseInt принимает второй аргумент как систему счисления, поэтому получает parseInt('2', 1) и parseInt('3', 2) — это NaN. Передавай функцию-обёртку или Number.

map и асинхронные функции

const ids = [1, 2, 3];
const promises = ids.map((id) => fetch(`/api/lessons/${id}`).then((r) => r.json()));
const lessons = await Promise.all(promises);

Если функция в map асинхронная, вернётся массив промисов, а не данных. Дождаться всех сразу помогает Promise.all — запросы при этом идут параллельно.

map, forEach, filter и reduce

Какой метод выбрать
НужноМетодВернёт
Преобразовать каждый элементmapновый массив той же длины
Оставить часть элементовfilterновый массив, возможно короче
Просто сделать действиеforEachundefined
Получить одно значениеreduceчто угодно: число, объект

map или forEach

map

Результат нужен: новый массив из преобразованных значений сохраняют в переменную или передают дальше.

forEach

Результат не нужен: вывести в консоль, добавить на страницу, отправить. map здесь создаст ненужный массив.

Частые ошибки

  • Открывают фигурные скобки и забывают return — получается массив undefined.
  • Возвращают объект без круглых скобок: (x) => { name: x }.
  • Используют map только ради побочного действия и никуда не сохраняют результат.
  • Меняют исходные объекты внутри map вместо создания новых.
  • Пишут map(parseInt) и получают NaN.

Доступность

Когда map строит элементы списка для страницы, оборачивай их в ul или ol и вставляй текст через textContent. Для интерактивных элементов создавай настоящие button и ссылки — скринридер и клавиатура работают с ними без дополнительного кода.

Поддержка браузерами

map входит в стандарт с ES5 и работает во всех браузерах. flatMap, spread в объектах и replaceChildren из примеров поддерживаются всеми актуальными браузерами.

Практика

Дан массив товаров { title, price }. Получи массив строк вида «Курс CSS — 1 500 ₽». Затем получи новый массив объектов с добавленным полем priceWithDiscount (минус 10%), не меняя исходные объекты.

Показать решение
const format = new Intl.NumberFormat('ru-RU');

const labels = products.map((p) => `${p.title} — ${format.format(p.price)} ₽`);

const discounted = products.map((p) => ({
  ...p,
  priceWithDiscount: Math.round(p.price * 0.9),
}));

Открыть песочницу

Частые вопросы

Меняет ли map исходный массив?

Нет, map возвращает новый массив. Но если внутри изменить поля объектов, изменятся и исходные объекты — создавай копии через spread.

Почему map вернул массив undefined?

В функции с фигурными скобками нет return. Добавь return или убери скобки, если тело — одно выражение.

Чем map отличается от forEach?

map возвращает новый массив из результатов функции. forEach ничего не возвращает и подходит для действий без результата.

Почему ['1','2','3'].map(parseInt) даёт NaN?

map передаёт вторым аргументом индекс, а parseInt принимает его как основание системы счисления. Используй map(Number) или (s) => parseInt(s, 10).

Как использовать map с async-функцией?

map вернёт массив промисов. Дождись их через await Promise.all(...).

Источники

Ещё в разделе JavaScript