$ sudo teach IT
РАЗДЕЛ 7 · УРОК 2

forEach и map: обходим и трансформируем массивы

Два самых часто используемых метода массивов. Оба принимают колбэк и проходят по каждому элементу — но делают это ради разных целей. Разберём разницу раз и навсегда.

⏱ ~20 минут 🎓 Для новичков 📦 JavaScript

🔄 forEach: просто пройди по каждому

Самый простой метод. Задача forEach — пройтись по каждому элементу массива и выполнить для него какое-то действие. Больше ничего: он ничего не возвращает (точнее, возвращает undefined).

Синтаксис прост: вы вызываете .forEach() на массиве и передаёте колбэк. Колбэк получит текущий элемент, его индекс и сам массив:

const fruits = ["яблоко", "банан", "вишня"];

fruits.forEach(function(fruit, index) {
  console.log(`${index}: ${fruit}`);
});
// → 0: яблоко
// → 1: банан
// → 2: вишня

Параметры колбэка: первый — это элемент (обязательный), второй — индекс (необязательный), третий — сам массив (необязательный). Если индекс не нужен — просто не указывайте его:

// Чаще всего нужен только элемент
fruits.forEach(fruit => {
  console.log("Фрукт: " + fruit);
});

// Важно: forEach ВСЕГДА возвращает undefined
const result = fruits.forEach(f => f.toUpperCase());
console.log(result); // → undefined

// Нельзя «сохранить результат» forEach — он для побочных эффектов!

💡 Когда использовать forEach: когда нужно что-то сделать для каждого элемента, но не нужен новый массив. Вывести в консоль, отрисовать в DOM, отправить запрос, обновить данные — всё это задачи для forEach.

🗺️ map: трансформируй и получи новый массив

map — это трансформация. Он проходит по каждому элементу, применяет к нему колбэк, и возвращает НОВЫЙ массив с результатами. Исходный массив при этом остаётся нетронутым.

Думайте о map как о «машине трансформации»: на входе один массив, на выходе — другой, такого же размера, но с изменёнными элементами.

const numbers = [1, 2, 3, 4, 5];

// map возвращает НОВЫЙ массив
const doubled = numbers.map(function(num) {
  return num * 2;
});

console.log(numbers); // → [1, 2, 3, 4, 5] — исходный не изменился!
console.log(doubled); // → [2, 4, 6, 8, 10] — новый массив

// Стрелочная функция — компактный стиль
const squared = numbers.map(num => num * num);
console.log(squared); // → [1, 4, 9, 16, 25]

Обратите внимание: map всегда возвращает новый массив той же длины. Каждый элемент нового массива — это то, что вернул колбэк для соответствующего элемента исходного массива.

🔑 Ключевое правило map: колбэк должен что-то вернуть (иначе в новом массиве будут undefined). Всегда используйте return или стрелку без фигурных скобок.

👥 map с массивом объектов

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

const users = [
  { name: "Алиса", age: 25, city: "Москва" },
  { name: "Боб", age: 30, city: "Питер" },
  { name: "Карл", age: 22, city: "Казань" }
];

// Извлечь только имена
const names = users.map(user => user.name);
console.log(names); // → ["Алиса", "Боб", "Карл"]

// Извлечь только возраст
const ages = users.map(user => user.age);
console.log(ages); // → [25, 30, 22]

// Создать строку-презентацию для каждого пользователя
const descriptions = users.map(user => {
  return `${user.name} (${user.age} лет, ${user.city})`;
});
console.log(descriptions);
// → ["Алиса (25 лет, Москва)", "Боб (30 лет, Питер)", "Карл (22 лет, Казань)"]

// Трансформировать структуру объекта
const simplified = users.map(user => ({
  fullInfo: `${user.name} из ${user.city}`,
  isAdult: user.age >= 18
}));
// → [{ fullInfo: "Алиса из Москвы", isAdult: true }, ...]

⚠️ Частая ошибка: при возврате объекта со стрелкой нужны двойные скобки: user => ({ key: val }). Без внешних скобок JS подумает, что фигурные скобки — это тело функции, а не объект.

🆚 forEach/map vs цикл for: когда что использовать

Вопрос, который задают все новички: «Зачем forEach и map, если есть привычный for?». Давайте сравним:

🔁 Цикл for

// map через for — много кода
const nums = [1, 2, 3, 4, 5];
const result = [];
for (let i = 0; i < nums.length; i++) {
  result.push(nums[i] * 2);
}
// result = [2, 4, 6, 8, 10]

Много «технического» кода: создай массив, итерируй по индексу, push. Цель (умножить на 2) теряется среди деталей.

✨ map

// То же самое через map
const nums = [1, 2, 3, 4, 5];
const result = nums.map(n => n * 2);
// result = [2, 4, 6, 8, 10]

Одна строка. Намерение очевидно: «умножь каждый элемент на 2». Код читается как описание задачи.

Когда всё же использовать for? Вот ситуации, где for лучше:

🛑 Нужно прервать цикл

forEach нельзя прервать с break. Для этого — for или for...of.

⚡ Критичная производительность

Для очень больших массивов (миллионы элементов) for чуть быстрее. Но обычно это незаметно.

🔀 Нестандартный шаг

Перебирать каждый второй элемент или в обратном порядке — проще с for.

💻 Практические примеры из реального кода

🛒 Корзина покупок — подсчёт суммы через forEach

const cart = [
  { name: "Ноутбук", price: 80000, qty: 1 },
  { name: "Мышь", price: 1500, qty: 2 },
  { name: "Клавиатура", price: 3000, qty: 1 }
];

let total = 0;
cart.forEach(item => {
  total += item.price * item.qty;
});

console.log(`Итого: ${total} ₽`); // → "Итого: 86000 ₽"

🌡️ Конвертация температур — классический map

const celsiusTemps = [0, 20, 37, 100];

// Celsius → Fahrenheit: F = C * 9/5 + 32
const fahrenheit = celsiusTemps.map(c => c * 9/5 + 32);
console.log(fahrenheit); // → [32, 68, 98.6, 212]

// Обратно: Fahrenheit → Celsius
const backToCelsius = fahrenheit.map(f => (f - 32) * 5/9);
console.log(backToCelsius); // → [0, 20, 37, 100]

📝 Рендер списка в React — map как основа

// В React это выглядит именно так (JSX)
const tasks = ["Купить молоко", "Позвонить маме", "Сдать проект"];

// map создаёт массив JSX-элементов
const listItems = tasks.map((task, index) => (
  `
  • ${task}
  • ` )); // В HTML: //
  • Купить молоко
  • //
  • Позвонить маме
  • //
  • Сдать проект
  • // map в React — это стандарт. Без него не обойтись!

    🎯 Итоговое правило выбора: используйте forEach, когда вам нужно выполнить действие для каждого элемента (вывести, обновить, отправить). Используйте map, когда нужен новый массив с преобразованными данными. Если нужно сохранить результат в переменную — это map.

    ✅ Итоги урока

    • forEach — перебирает массив, вызывает колбэк для каждого элемента, возвращает undefined
    • map — перебирает массив, применяет колбэк, возвращает новый массив с результатами
    • Исходный массив ни forEach, ни map не изменяют
    • В колбэке map обязательно нужен return, иначе получите массив из undefined
    • map идеален для трансформаций: умножить числа, извлечь поле из объектов, конвертировать единицы
    • forEach — для побочных эффектов: вывод, DOM-манипуляции, обновление внешних переменных
    • map — основа рендеринга списков в React и других фреймворках

    В следующем уроке изучим filter, find, some и every — методы для поиска и фильтрации данных в массивах. 🔍

    forEach и map

    6 вопросов

    Подсчёт корзины через forEach

    Дан массив cart с объектами { name, price, qty }. Используя forEach, подсчитайте общую сумму заказа total (цена × количество по каждому товару) и верните её.

    Трансформация массива объектов через map

    Дан массив пользователей users с полями { name, age, city }. Используя map, создайте массив строк вида 'Name (Age, City)' для каждого пользователя. Например: 'Анна (25, Москва)'.