Справочник · JavaScript
Array.map(): преобразуем каждый элемент
Метод 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);| Параметр | Что это |
|---|---|
element | текущий элемент |
index | его индекс, необязательный |
array | сам массив, необязательный |
thisArg | this для обычной функции; со стрелкой не нужен |
| Возвращает | новый массив той же длины |
Преобразование объектов
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 | новый массив, возможно короче |
| Просто сделать действие | forEach | undefined |
| Получить одно значение | reduce | что угодно: число, объект |
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(...).