Пошук уроків, статей та іншого контенту
Декларативна обробка масивів замість ручних циклів — три найважливіші методи масивів.
Цикл for...of з попереднього модуля може зробити все те саме — але він описує як виконати обробку (створи порожній масив, перебери елементи, доклади результат). map/filter/reduce описують що потрібно зробити з даними — це декларативний стиль, який зазвичай коротший, менш схильний до помилок (немає ручного керування індексом чи проміжним масивом) і одразу повідомляє наміри коду самою назвою методу.
map створює новий масив тієї ж довжини, застосувавши функцію до кожного елемента:
const prices = [100, 200, 300];
const withTax = prices.map((price) => price * 1.2);
withTax; // [120, 240, 360]
prices; // [100, 200, 300] — оригінал не змінивсяКолбек у map обов'язково має щось повертати — забутий return (наприклад, у функції з фігурними дужками) поверне масив із undefined замість очікуваних значень.
filter створює новий масив із тих елементів, для яких колбек повернув truthy-значення. Довжина результату зазвичай менша за оригінал:
const numbers = [1, 2, 3, 4, 5, 6];
const evens = numbers.filter((n) => n % 2 === 0);
evens; // [2, 4, 6]Найгнучкіший і найскладніший для розуміння з трьох. reduce проходить масив зліва направо, на кожному кроці передаючи «накопичувач» (accumulator) від попереднього кроку до наступного, і в кінці повертає єдине значення:
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
// ^ початкове значення accumulator
// Крок за кроком:
// accumulator=0, current=1 → повертає 1
// accumulator=1, current=2 → повертає 3
// accumulator=3, current=3 → повертає 6
// accumulator=6, current=4 → повертає 10
sum; // 10Другий аргумент reduce (початкове значення) легко забути — без нього перший елемент масиву стає початковим accumulator, що для порожнього масиву кине помилку, а для операцій, відмінних від простого додавання, часто дає неправильний результат. Завжди передавайте явний початковий елемент.
reduce не обмежений числами — накопичувачем може бути об'єкт, масив чи будь-яка інша структура:
const words = ["яблуко", "банан", "яблуко", "вишня", "банан", "яблуко"];
const counts = words.reduce((acc, word) => {
acc[word] = (acc[word] ?? 0) + 1;
return acc; // не забути повернути накопичувач на кожному кроці!
}, {});
counts; // { яблуко: 3, банан: 2, вишня: 1 }Оскільки map і filter повертають новий масив, їх можна поєднувати послідовно — кожен наступний метод працює з результатом попереднього:
const orders = [
{ id: 1, total: 250, paid: true },
{ id: 2, total: 80, paid: false },
{ id: 3, total: 500, paid: true },
];
const paidTotal = orders
.filter((order) => order.paid)
.map((order) => order.total)
.reduce((sum, total) => sum + total, 0);
paidTotal; // 750 — сума лише оплачених замовленьconst products = [
{ name: "Ноутбук", category: "Електроніка" },
{ name: "Хліб", category: "Продукти" },
{ name: "Телефон", category: "Електроніка" },
];
const byCategory = products.reduce((acc, product) => {
const category = product.category;
acc[category] = acc[category] ?? [];
acc[category].push(product.name);
return acc;
}, {});
// { "Електроніка": ["Ноутбук", "Телефон"], "Продукти": ["Хліб"] }Забутий return у колбеку map/reduce — особливо в багаторядковій стрілковій функції з фігурними дужками.
Виклик map, коли насправді потрібен forEach (побічний ефект без потреби в новому масиві) — map створює масив, навіть якщо результат ніде не використовується, що витрачає пам'ять даремно.
Забуте початкове значення в reduce.
Використання filter().length замість прямого підрахунку, коли потрібна лише кількість елементів, що відповідають умові — зайве створення проміжного масиву.
map перетворює кожен елемент у щось нове, filter залишає лише потрібні, reduce зводить масив до одного підсумкового значення. Усі три не змінюють оригінальний масив і повертають новий результат, тому їх безпечно комбінувати в ланцюжок — це основний робочий інструмент для обробки списків даних у сучасному JavaScript.
Спробуйте самостійно
Маючи масив const students = [{ name: "Оля", grade: 92 }, { name: "Іван", grade: 65 }, { name: "Марія", grade: 78 }], отримайте масив імен студентів з оцінкою 75 і вище, використовуючи filter та map у ланцюжку.