Справочник · JavaScript
Array.filter(): оставляем подходящие элементы
Метод filter() перебирает массив, вызывает для каждого элемента функцию-условие и возвращает новый массив только с теми элементами, для которых функция вернула истинное значение. Исходный массив не меняется. Если ни один элемент не подошёл, получится пустой массив [].
arr.filter((item) => условие)— новый массив из подходящих элементов.- Исходный массив остаётся прежним.
- Результат всегда массив, даже из одного элемента или пустой.
- Нужен один элемент —
find, нужен ответ «есть ли» —some. - В функции с фигурными скобками нужен
return.
Минимальный пример
const prices = [120, 600, 350, 900];
const expensive = prices.filter((price) => price >= 500);
console.log(expensive); // [600, 900]
console.log(prices); // [120, 600, 350, 900] — не изменилсяФункция получает каждую цену по очереди и возвращает true или false. В результат попадают только цены, для которых вернулось true.
Синтаксис и параметры
const result = array.filter(callback(element, index, array), thisArg);| Параметр | Что это |
|---|---|
element | текущий элемент |
index | его индекс, необязательный |
array | сам массив, необязательный |
thisArg | значение this внутри обычной функции; со стрелочными функциями не нужен |
| Возвращает | новый массив; элементы копируются по ссылке |
Функция не обязана возвращать именно true: подойдёт любое истинное значение. Непустая строка, число, кроме нуля, объект — истинны; 0, '', null, undefined, NaN — ложны.
Фильтрация массива объектов
const lessons = [
{ title: 'HTML', published: true, minutes: 15 },
{ title: 'CSS', published: false, minutes: 20 },
{ title: 'JavaScript', published: true, minutes: 30 },
];
const visible = lessons.filter((lesson) => lesson.published);
const short = lessons.filter(({ minutes }) => minutes <= 20);
const both = lessons.filter((l) => l.published && l.minutes <= 20);Это самый частый случай: оставить опубликованные статьи, товары в наличии, активных пользователей. Несколько условий соединяют через && (все сразу) или || (хотя бы одно).
Поиск по тексту
function search(items, query) {
const q = query.trim().toLowerCase();
if (!q) return items;
return items.filter((item) => item.title.toLowerCase().includes(q));
}
search(lessons, 'java'); // [{ title: 'JavaScript', … }]Обе строки приводятся к одному регистру, иначе «Java» не найдётся по запросу «java». Пустой запрос возвращает весь список — так фильтр не прячет всё, пока человек ничего не ввёл.
Полезные приёмы
// убрать пустые значения: '', 0, null, undefined, NaN, false
const clean = ['HTML', '', null, 'CSS'].filter(Boolean); // ['HTML', 'CSS']
// убрать дубли
const tags = ['css', 'html', 'css'];
const unique = tags.filter((tag, i, arr) => arr.indexOf(tag) === i); // ['css', 'html']
// короче через Set: [...new Set(tags)]
// удалить элемент по id, не меняя исходный массив
const rest = tasks.filter((task) => task.id !== idToRemove);filter(Boolean) передаёт каждый элемент в функцию Boolean, и остаются только истинные. Удаление через filter — стандартный приём в React и Vue: состояние меняют, создавая новый массив, а не правя старый.
Цепочки filter и map
const titles = lessons
.filter((lesson) => lesson.published)
.map((lesson) => lesson.title);
// ['HTML', 'JavaScript']filter сначала отбирает, map потом преобразует. Порядок важен: если сначала сделать map в строки, поле published уже потеряется.
filter, find, some и findIndex
| Нужно | Метод | Вернёт |
|---|---|---|
| Все подходящие | filter | массив, возможно пустой |
| Первый подходящий | find | элемент или undefined |
| Индекс первого подходящего | findIndex | число или -1 |
| Есть ли хоть один | some | true / false |
| Подходят ли все | every | true / false |
Если нужен один пользователь по id, filter(...)[0] работает, но перебирает весь массив и читается хуже, чем find.
Как filter работает внутри
filter проходит элементы по порядку один раз. Пустые слоты в разреженном массиве (например, после delete arr[1]) пропускаются. Элементы, добавленные в массив во время перебора, не обрабатываются. Результат — поверхностная копия: объекты внутри нового массива те же самые, что в исходном, поэтому изменение visible[0].title изменит и объект в lessons.
filter или цикл for
Коротко, не меняет исходный массив, легко сцепить с map и sort. Подходит в большинстве случаев.
Нужен, если по ходу надо прервать перебор (break) или сделать сразу несколько действий над элементом.
Частые ошибки
- Пишут стрелочную функцию с фигурными скобками без
return:filter((x) => { x > 5 })вернёт пустой массив. - Ждут от filter один объект и обращаются к
result.title— это массив, нуженfindилиresult[0]. - Передают async-функцию: она возвращает Promise, а он всегда истинный, и в результат попадает всё.
- Меняют исходный массив внутри callback через
splice. - Сравнивают строки без приведения к одному регистру в поиске.
Доступность
Если фильтр меняет список на странице, сообщи результат скринридеру: обнови счётчик «Найдено: 3» в элементе с aria-live="polite". Пустой результат показывай текстом «Ничего не найдено», а не просто пустым местом — иначе неясно, сломалось что-то или подходящих элементов нет.
Поддержка браузерами
filter входит в стандарт с ES5 (2009) и работает во всех браузерах и в Node.js. Стрелочные функции, деструктуризация в параметрах и Set из примеров работают во всех актуальных браузерах.
Практика
Дан массив пользователей { name, age, isActive }. Оставь совершеннолетних и активных, затем получи массив только их имён. Отдельно напиши функцию, которая удаляет пользователя по имени и не меняет исходный массив.
Показать решение
const adults = users.filter((user) => user.age >= 18 && user.isActive);
const names = adults.map((user) => user.name);
function removeUser(list, name) {
return list.filter((user) => user.name !== name);
}Частые вопросы
Меняет ли filter исходный массив?
Нет. filter всегда возвращает новый массив, а исходный остаётся прежним. Но объекты внутри общие: если изменить поле объекта в результате, оно изменится и в исходном массиве.
Почему filter вернул пустой массив?
Чаще всего в стрелочной функции с фигурными скобками забыли return, и функция возвращает undefined. Либо условие действительно не подошло ни одному элементу.
Как получить один элемент вместо массива?
Используй find: он вернёт первый подходящий элемент или undefined. filter возвращает массив всегда.
Как удалить элемент из массива через filter?
Оставь всё, кроме него: list.filter((item) => item.id !== id). Получится новый массив без этого элемента.
Можно ли использовать async-функцию в filter?
Нет: async-функция возвращает Promise, а он всегда истинный. Сначала дождись проверок через Promise.all, потом фильтруй по полученным результатам.