Пошук уроків, статей та іншого контенту
Навчитеся відбирати елементи та перевіряти масиви методами filter, every і some.
Масиви часто містять більше даних, ніж потрібно для конкретної операції. Наприклад:
показати лише активних користувачів;
знайти всі товари дешевші за певну суму;
перевірити, чи всі значення відповідають умові;
перевірити, чи є хоча б один елемент, що відповідає умові.
Для таких завдань використовують методи:
filter() — відбирає всі елементи, які відповідають умові;
every() — перевіряє, чи всі елементи відповідають умові;
some() — перевіряє, чи хоча б один елемент відповідає умові.
Усі ці методи приймають callback-функцію, яка викликається для кожного елемента масиву.
filter()Метод filter() створює новий масив із елементів, для яких callback повернув true.
const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = numbers.filter((number) => {
return number % 2 === 0;
});
console.log(evenNumbers); // [2, 4, 6]
console.log(numbers); // [1, 2, 3, 4, 5, 6]Початковий масив не змінюється. Це важлива відмінність від методів, які змінюють масив, наприклад push() або splice().
Якщо callback складається з одного виразу, його можна записати коротше:
const prices = [120, 450, 80, 999, 300];
const affordablePrices = prices.filter((price) => price < 500);
console.log(affordablePrices); // [120, 450, 80, 300]На практиці filter() часто використовують для масивів об'єктів.
const users = [
{ name: "Olena", isActive: true },
{ name: "Andrii", isActive: false },
{ name: "Marta", isActive: true },
];
const activeUsers = users.filter((user) => user.isActive);
console.log(activeUsers);
// [
// { name: "Olena", isActive: true },
// { name: "Marta", isActive: true }
// ]Умова user.isActive повертає булеве значення, тому додаткова перевірка === true не потрібна.
Callback для filter() може отримувати три аргументи:
поточний елемент;
індекс поточного елемента;
початковий масив.
const words = ["JavaScript", "HTML", "CSS", "TypeScript"];
const longWords = words.filter((word, index) => {
console.log(`Індекс ${index}: ${word}`);
return word.length > 3;
});
console.log(longWords); // ["JavaScript", "TypeScript"]Третій параметр рідше потрібен у звичайних задачах, але він доступний:
const numbers = [10, 20, 30];
const result = numbers.filter((number, index, array) => {
// Перевіряємо, що поточний елемент не є останнім
return index < array.length - 1;
});
console.log(result); // [10, 20]every()Метод every() перевіряє, чи відповідають умові всі елементи масиву.
Результатом завжди є true або false.
const ages = [18, 21, 35, 42];
const allAdults = ages.every((age) => age >= 18);
console.log(allAdults); // trueЯкщо хоча б один елемент не відповідає умові, метод одразу повертає false.
const scores = [90, 84, 72, 45];
const allPassed = scores.every((score) => score >= 60);
console.log(allPassed); // falseМетод every() припиняє перебір після першого невдалого результату. Це називають коротким замиканням перебору.
every() зручно використовувати, коли потрібно перевірити, чи всі елементи мають потрібний тип або властивість.
const values = [10, 25, 7, 42];
const containsOnlyNumbers = values.every((value) => {
return typeof value === "number";
});
console.log(containsOnlyNumbers); // trueПеревірка масиву об'єктів:
const products = [
{ name: "Keyboard", price: 1500 },
{ name: "Mouse", price: 800 },
{ name: "Monitor", price: 7000 },
];
const productsHavePrices = products.every((product) => {
return typeof product.price === "number" && product.price >= 0;
});
console.log(productsHavePrices); // truesome()Метод some() перевіряє, чи є в масиві хоча б один елемент, який відповідає умові.
const numbers = [3, 7, 11, 14];
const hasEvenNumber = numbers.some((number) => number % 2 === 0);
console.log(hasEvenNumber); // trueУ цьому прикладі достатньо знайти число 14, тому після цього перебір припиняється.
Якщо жоден елемент не відповідає умові, результатом буде false:
const numbers = [1, 3, 5, 7];
const hasEvenNumber = numbers.some((number) => number % 2 === 0);
console.log(hasEvenNumber); // falseconst users = [
{ name: "Olena", role: "user" },
{ name: "Andrii", role: "admin" },
{ name: "Marta", role: "user" },
];
const hasAdmin = users.some((user) => user.role === "admin");
if (hasAdmin) {
console.log("У системі є адміністратор");
}filter(), every() і some()Розглянемо один масив і три різні запити:
const numbers = [2, 4, 7, 10, 12];
const evenNumbers = numbers.filter((number) => number % 2 === 0);
const allEven = numbers.every((number) => number % 2 === 0);
const hasEven = numbers.some((number) => number % 2 === 0);
console.log(evenNumbers); // [2, 4, 10, 12]
console.log(allEven); // false
console.log(hasEven); // trueМетоди відповідають на різні запитання:
filter() — «Які саме елементи відповідають умові?»
every() — «Чи всі елементи відповідають умові?»
some() — «Чи є хоча б один елемент, що відповідає умові?»
Методи можна використовувати разом. Наприклад, спочатку відібрати активних користувачів, а потім перевірити, чи є серед них адміністратор.
const users = [
{ name: "Olena", isActive: true, role: "user" },
{ name: "Andrii", isActive: false, role: "admin" },
{ name: "Marta", isActive: true, role: "admin" },
];
const activeUsers = users.filter((user) => user.isActive);
const hasActiveAdmin = activeUsers.some((user) => user.role === "admin");
console.log(activeUsers);
// [
// { name: "Olena", isActive: true, role: "user" },
// { name: "Marta", isActive: true, role: "admin" }
// ]
console.log(hasActiveAdmin); // trueУ простому випадку те саме можна записати одним ланцюжком:
const hasActiveAdmin = users
.filter((user) => user.isActive)
.some((user) => user.role === "admin");
console.log(hasActiveAdmin); // trueОднак не варто без потреби створювати проміжний масив. Якщо потрібна лише відповідь «так» або «ні», умову можна об'єднати:
const hasActiveAdmin = users.some((user) => {
return user.isActive && user.role === "admin";
});
console.log(hasActiveAdmin); // trueТакий варіант простіший і не створює додатковий масив.
Нехай є список товарів інтернет-магазину:
const products = [
{ name: "Ноутбук", price: 32000, inStock: true, category: "electronics" },
{ name: "Навушники", price: 2500, inStock: true, category: "electronics" },
{ name: "Книга", price: 600, inStock: false, category: "books" },
{ name: "Рюкзак", price: 1800, inStock: true, category: "accessories" },
];Отримаємо товари в наявності:
const availableProducts = products.filter((product) => product.inStock);
console.log(availableProducts);Отримаємо товари категорії electronics:
const electronics = products.filter((product) => {
return product.category === "electronics";
});
console.log(electronics);Перевіримо, чи всі товари мають додатну ціну:
const allPricesAreValid = products.every((product) => {
return product.price > 0;
});
console.log(allPricesAreValid); // trueПеревіримо, чи є товар дешевший за 1000:
const hasCheapProduct = products.some((product) => {
return product.price < 1000;
});
console.log(hasCheapProduct); // trueДля порожнього масиву методи повертають такі значення:
console.log([].filter(() => true)); // []
console.log([].every(() => false)); // true
console.log([].some(() => true)); // falseПоведінка every() може здаватися неочікуваною: він повертає true, бо в порожньому масиві немає жодного елемента, який порушує умову.
Це важливо враховувати під час перевірки даних:
const tasks = [];
const allTasksCompleted = tasks.every((task) => task.completed);
console.log(allTasksCompleted); // trueЯкщо порожній масив не повинен вважатися успішним результатом, додайте окрему перевірку:
const allTasksCompleted =
tasks.length > 0 && tasks.every((task) => task.completed);
console.log(allTasksCompleted); // falseУ filter(), every() і some() callback визначає результат за значенням, яке він повертає.
Правильний варіант:
const positiveNumbers = [-2, 0, 4, 7].filter((number) => number > 0);
console.log(positiveNumbers); // [4, 7]Якщо використовується фігурне тіло стрілкової функції, потрібно явно написати return:
const positiveNumbers = [-2, 0, 4, 7].filter((number) => {
return number > 0;
});
console.log(positiveNumbers); // [4, 7]Поширена помилка:
const positiveNumbers = [-2, 0, 4, 7].filter((number) => {
number > 0;
});
console.log(positiveNumbers); // []У цьому випадку callback нічого не повертає. Фактично він повертає undefined, яке інтерпретується як false.
filter() замість some()Якщо потрібно лише перевірити факт наявності елемента, не обов'язково створювати новий масив.
const hasLargeNumber = numbers.some((number) => number > 100);Замість:
const largeNumbers = numbers.filter((number) => number > 100);
const hasLargeNumber = largeNumbers.length > 0;Другий варіант працює, але є менш прямим і створює зайвий масив.
filter() змінить початковий масивconst numbers = [1, 2, 3];
numbers.filter((number) => number > 1);
console.log(numbers); // [1, 2, 3]Результат filter() потрібно зберегти або використати далі:
const numbers = [1, 2, 3];
const filteredNumbers = numbers.filter((number) => number > 1);
console.log(filteredNumbers); // [2, 3]every() і some()const scores = [80, 90, 45];
const allPassed = scores.every((score) => score >= 60);
const atLeastOnePassed = scores.some((score) => score >= 60);
console.log(allPassed); // false
console.log(atLeastOnePassed); // trueevery() вимагає, щоб умові відповідали всі елементи, а some() — лише один або більше.
const users = [
{ name: "Olena", isActive: true },
{ name: "Andrii", isActive: "true" },
];
const allActive = users.every((user) => user.isActive === true);
console.log(allActive); // falseРядок "true" і булеве значення true — різні значення. Для надійної перевірки враховуйте тип даних.
Створіть масив чисел і за допомогою filter() отримайте лише числа, кратні трьом.
Перевірте через every(), чи всі числа масиву є додатними.
Перевірте через some(), чи є в масиві число 0.
Із масиву користувачів отримайте лише повнолітніх користувачів.
Перевірте, чи є хоча б один товар у наявності та дешевший за 1000.
Перевірте, чи всі товари мають непорожню назву.
filter() повертає новий масив із усіма елементами, що відповідають умові.
every() повертає true, якщо умові відповідають усі елементи.
some() повертає true, якщо умові відповідає хоча б один елемент.
Початковий масив ці методи не змінюють.
Callback має повертати значення, яке можна інтерпретувати як true або false.
every() і some() можуть завершити перебір раніше, щойно результат стає очевидним.
Для порожнього масиву every() повертає true, а some() — false.
Методи можна комбінувати, але варто обирати найпряміший варіант для конкретного завдання.