forEach.map.filter.reduce.find, findIndex, some, every, sort.Більшість часу фронтенд-розробник працює зі списками даних, які отримує від сервера (бек-енду). Це може бути список товарів в інтернет-магазині, список повідомлень у чаті або список транзакцій у банківському додатку. У JavaScript такі списки завжди представлені у вигляді Масивів Об’єктів (Array of Objects).
До виходу стандарту ES6 для перебору масивів використовували класичний цикл for. Цей підхід змушував писати багато зайвого коду і вручну керувати лічильниками (let i = 0).
Сучасний JavaScript надає розробникам потужний набір декларативних методів (наприклад, map, filter, reduce), які дозволяють виконувати складні операції з даними в один або два рядки коду, роблячи його чистішим і набагато читабельнішим.
Саме глибоке розуміння та вільне володіння цими методами відрізняє початківця від професійного розробника (Junior vs Middle). Ці методи також критично важливі для роботи з сучасними фреймворками, такими як React (де метод map — це основний спосіб відмальовки списків HTML на сторінці).
Імперативний підхід (Як зробити?):
Ви описуєте комп’ютеру кожен крок, розжовуючи деталі. Класичний цикл for — це імперативщина. Ви повинні самостійно створити лічильник i, самостійно перевіряти, чи досяг він кінця масиву, і самостійно його збільшувати.
Декларативний підхід (Що я хочу отримати?):
Ви лише вказуєте комп’ютеру кінцевий результат, який вас цікавить, за допомогою готових методів. Усі “брудні” деталі (лічильники, перевірки довжини) заховані всередині цих методів і працюють автоматично.
Сучасні методи масивів в JS (map, filter, reduce) — це яскравий приклад декларативного підходу.
Усі перелічені нижче методи працюють за одним принципом: вони приймають Callback-функцію як свій єдиний аргумент. Метод самостійно “пробігається” по всьому масиву від першого до останнього елемента і, на кожному кроці, викликає вашу Callback-функцію, передаючи їй поточний елемент, його індекс та, власне, сам масив.
const numbers = [10, 20, 30];
// Синтаксис Callback в методах (зазвичай використовують стрілочні функції)
numbers.someMethod((element, index, array) => {
// Тіло вашої функції: що робити з кожним element?
});
Важливо: У більшості випадків нам потрібен лише перший параметр (
element), аindexтаarrayми просто опускаємо (не пишемо).
forEachМетод forEach (“для кожного”) — це пряма, сучасна і більш зручна альтернатива циклу for.
Він просто бере кожен елемент масиву і щось з ним робить (наприклад, виводить у консоль або змінює зовнішню змінну).
Ключова особливість: forEach завжди повертає undefined. Він нічого не створює, він лише виконує дію.
Метод forEach не можна перервати break або continue (як це можна зробити у звичайному for).
const students = ["Іван", "Петро", "Марія"];
// Виведе кожне ім'я в консоль
students.forEach((student) => {
console.log(`Студент: ${student}`);
});
mapМетод map (“відображення” / “карта”) — мабуть, найважливіший метод у сучасному вебі.
Він використовується, коли ми маємо один масив, і хочемо створити з нього новий масив, де кожен елемент буде якось модифіковано (трансформовано).
Ключові особливості map:
return) якесь значення. Те, що повертає Callback для поточного елемента, записується у новий масив.const prices = [100, 250, 400];
const discount = 0.9; // Знижка 10%
// Створюємо новий масив discountedPrices
const discountedPrices = prices.map((price) => price * discount);
console.log(prices); // [100, 250, 400] (Оригінал не змінився)
console.log(discountedPrices); // [90, 225, 360] (Новий масив)
У React метод map використовується для трансформації масиву даних (об’єктів) у візуальні елементи JSX (наприклад, у теги <li> чи <Card>).
filterЯк зрозуміло з назви, filter потрібен для відсіювання елементів.
Ви передаєте йому Callback-функцію з перевіркою (умовою). Якщо умова повертає true — елемент проходить фільтр і потрапляє у новий масив. Якщо false — елемент ігнорується.
Ключові особливості filter:
[]), якщо не всі елементи пройшли перевірку.const users = [
{ name: "Анна", age: 17 },
{ name: "Олег", age: 25 },
{ name: "Ігор", age: 15 },
];
// Залишаємо лише повнолітніх (age >= 18)
const adults = users.filter((user) => user.age >= 18);
console.log(adults); // Отримаємо масив з одним об'єктом: [{ name: "Олег", age: 25 }]
reduceЦе найскладніший, але найбільш універсальний метод.
reduce застосовується, коли потрібно “згорнути” (агрегувати) величезний масив в одне єдине фінальне значення (наприклад, знайти загальну суму всієї корзини покупок, знайти найдорожчий товар, або згрупувати масив об’єктів у словник).
Callback у reduce трохи відрізняється — він приймає 4 аргументи, але найважливішими є перші два:
accumulator (Акумулятор) — проміжний результат, який “накопичується” при проході по масиву. З кожним кроком у ньому зберігається те, що повернув Callback на попередньому кроці.currentValue — поточний елемент масиву (як в map або filter).Також метод reduce приймає другий загальний аргумент (після Callback’у) — початкове значення акумулятора (Initial Value).
const orders = [500, 1000, 2500];
// accumulator (acc) тут виступає як "загальна сума".
// Початкове значення (0) ми передали після коми в кінці методу.
const totalSum = orders.reduce((acc, currentVal) => {
return acc + currentVal;
}, 0);
console.log(totalSum); // 4000
Як це працювало всередині:
find, some, every)find та findIndexШукає в масиві перший об’єкт, який відповідає умові.
Якщо знаходить — одразу повертає сам об’єкт (а не масив) і перериває пошук. Якщо не знайдено нічого — повертає undefined.
findIndex робить те саме, але повертає не сам об’єкт, а його індекс (порядковий номер) у масиві (або -1 якщо не знайдено).
/* Приклад: знайти користувача з id === 3 */
const foundUser = dbUsers.find((user) => user.id === 3);
some та everyПовертають лише true або false (Boolean). Корисні для перевірок дозвілів чи валідації.
some: Перевіряє, чи є в масиві ХОЧА Б ОДИН елемент, що відповідає умові.every: Перевіряє, чи АБСОЛЮТНО ВСІ елементи відповідають умові.const ages = [18, 20, 16, 21];
const hasMinors = ages.some((age) => age < 18); // true (бо є 16)
const allAdults = ages.every((age) => age >= 18); // false (бо є 16)
sortВикористовується для сортування масивів (наприклад, сортування товарів за ціною з найменшої).
Обережно (Мутація): На відміну від map або filter, метод sort змінює (“мутує”) оригінальний масив!
Якщо сортувати без Callback-функції, sort перетворює всі значення на рядки тексту і сортує їх за абеткою (тоді 10 буде стояти перед 2).
Для чисел потрібно передавати Callback (a, b):
const nums = [40, 100, 1, 5, 25];
// Сортування за зростанням
nums.sort((a, b) => a - b); // [1, 5, 25, 40, 100]
// Сортування за спаданням
nums.sort((a, b) => b - a); // [100, 40, 25, 5, 1]
Оскільки map та filter завжди повертають нові масиви, ми можемо застосовувати їх один за одним у вигляді ланцюжка (Chaining). Кожен наступний метод застосовується до результату роботи попереднього. Точка ставиться відразу після закриваючої дужки попереднього методу.
Задача: Дано масив продуктів. Потрібно знайти всі товари, що дешевші за 50 грн, і отримати масив лише з їхніх назв (рядків), записаних Великими Літерами.
const products = [
{ name: "Хліб", price: 20 },
{ name: "Сир", price: 150 },
{ name: "Молоко", price: 35 },
];
const cheapProductNames = products
.filter((product) => product.price < 50) // Крок 1: Залишаємо [Хліб, Молоко]
.map((product) => product.name.toUpperCase()); // Крок 2: Трансформуємо у ["ХЛІБ", "МОЛОКО"]
console.log(cheapProductNames); // ["ХЛІБ", "МОЛОКО"]
Такий підхід дозволяє створювати надзвичайно потужні потоки обробки даних, уникаючи створення зайвих проміжних змінних (на кшталт filteredArr, finalArr тощо).
for до методів масивів (map, filter) означає перехід від імперативного до декларативного стилю програмування (ваш код стає коротшим і зрозумілішим).forEach є заміною for і використовується лише для того, щоб “щось зробити” з кожним елементом, але він нічого не повертає.map створює та повертає новий масив тієї ж довжини (використовується для трансформації об’єктів або рендерингу).filter створює новий масив, відкидаючи елементи, що не відповідають заданій умові.reduce вміє згортати цілий масив у будь-яке єдине значення завдяки змінній accumulator.find ідеально підходить для пошуку одного унікального об’єкта в базі за його id.sort — небезпечний, оскільки мутує оригінальний масив і вимагає написання математичної callback-перевірки (a, b) => a - b.map, filter, sort), можна об’єднувати у довгі елегантні ланцюжки (Chaining).map, filter, reduce за 15 хвилин.forEach та map? У яких випадках слід обрати кожен із них?map ви забудете написати команду return? Яким буде результат (масив з чим)?filter отримав Callback, який завжди повертає число 1. Що буде у відфільтрованому масиві?accumulator у методі reduce, і де в синтаксисі вказується початкове значення цього акумулятора?find буде набагато ефективнішим вибором (з точки зору швидкодії сервера), ніж метод filter?[5, 1, 15]. Яким буде результат виклику arr.sort() без переданої Callback-функції і чому?filter або map він став можливим?