Перейти к содержимому
Теория · Методы массивов · урок 2 из 12

map и filter

В прошлом уроке работник у конвейера только ставил штампы, а готовые вещи никуда не попадали. Часто же из одного массива нужно получить другой: цены со скидкой или только положительные числа.

С forEach новый массив пришлось бы собирать вручную через push, ведь сам метод возвращает undefined. Представьте, что у конвейера появилась вторая лента. Работник берёт ящик с первой ленты, а на вторую кладёт то, что получилось. Так работает метод map: он сам собирает новый массив.

JavaScript
const prices = [10, 25, 40];
const doubled = prices.map((p) => p * 2);

console.log(doubled); // [ 20, 50, 80 ]
console.log(prices); // [ 10, 25, 40 ]

Давайте разберём пример по строкам:

  1. prices — массив из трёх цен.
  2. prices.map((p) => p * 2) вызывает колбэк для каждой цены и собирает ответы колбэка в новый массив doubled.
  3. Первый вызов console.log печатает [ 20, 50, 80 ].
  4. Второй печатает [ 10, 25, 40 ]: исходный массив остался прежним.

map преобразует каждый элемент

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

Здесь аналогия с лентами хромает. На настоящей фабрике ящик уходит с первой ленты, а массив prices после map остаётся целым, со всеми элементами на своих местах.

map подходит, когда каждому элементу нужен ровно один результат: цене — скидка, имени — заглавные буквы. Колбэк получает элемент и его индекс, как в forEach.

Возвращать колбэк может значение любого типа. Вызов ["ann", "bob"].map((name) => name.toUpperCase()) даёт массив строк ["ANN", "BOB"].

Разницу между map и forEach часто спрашивают на собеседовании. Ответ короткий: map возвращает новый массив из результатов колбэка, а forEach всегда возвращает undefined.

filter оставляет часть

Теперь у ленты стоит контролёр. Он смотрит на каждый ящик и решает: пропустить его на вторую ленту или снять. Так работает filter.

filter тоже вызывает колбэк для каждого элемента, но результат колбэка служит условием. В новый массив попадают сами элементы, для которых колбэк вернул истинное значение. Остальные отбрасываются, поэтому новый массив бывает короче исходного или вовсе пустым.

Колбэк не обязан возвращать именно true или false: его результат проверяется так же, как условие в if.

JavaScript
const nums = [4, 7, 10, 3];

console.log(nums.filter((n) => n > 5)); // [ 7, 10 ]
console.log(nums.filter((n) => n > 100)); // []

Разберём оба вызова:

  • условие n > 5 выполняется для 7 и 10, и filter возвращает [ 7, 10 ];
  • условие n > 100 не выполняется ни для одного числа, и результат — пустой массив [].

filter тоже не меняет исходный массив: в nums по-прежнему четыре числа.

Цепочка вызовов

map и filter возвращают массив, поэтому у результата можно сразу вызвать следующий метод. Такую запись называют цепочкой вызовов. Методы выполняются слева направо, и каждый работает с массивом, который вернул предыдущий:

JavaScript
const scores = [55, 90, 72, 40];
const raised = scores.filter((s) => s >= 60).map((s) => s + 5);

console.log(raised.join(" ")); // 95 77

Цепочка похожа на две станции на одном конвейере. Давайте пройдём их по порядку:

  1. filter пропускает только баллы от 60, и получается [90, 72].
  2. map прибавляет 5 только к этим двум числам и возвращает [95, 77].
  3. join(" ") склеивает их в строку 95 77.

Порядок станций важен. Если поменять методы местами, filter проверит уже увеличенные числа.

Частая ошибка

Из массива хотели оставить чётные числа, а в условии написали только остаток:

JavaScript
const nums = [1, 2, 3, 4];
const evens = nums.filter((n) => n % 2); // ✗

console.log(evens);

Ошибки нет, но программа выводит [ 1, 3 ]. У чётного числа остаток 0 — ложное значение, и filter такой элемент отбрасывает. У нечётного остаток 1 — истинное значение, и элемент остаётся. Сравните остаток с нулём: nums.filter((n) => n % 2 === 0) даёт [ 2, 4 ].

Главное

  • map возвращает новый массив той же длины из результатов колбэка.
  • filter возвращает новый массив из элементов, для которых колбэк вернул истинное значение.
  • Оба метода не меняют исходный массив и возвращают новый, поэтому их вызовы соединяют в цепочку.
  • В отличие от map, forEach всегда возвращает undefined.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом