Для чего нужны и как работают методы массивов map, filter и reduce в JavaScript
Что проверяют
Понимаете ли вы, что все три не изменяют исходный массив, и знаете ли ловушки reduce.
Как отвечать
mapпреобразует каждый элемент и возвращает новый массив той же длины;filterотбирает элементы по предикату, длина результата меньше или равна исходной;reduceсворачивает массив в одно значение с помощью аккумулятора.
const ids = jobs.map((j) => j.id);
const active = jobs.filter((j) => j.isActive);
const total = jobs.reduce((sum, j) => sum + j.salary, 0);Общее свойство: исходный массив не изменяется, возвращается новый. Это делает их удобными в декларативном коде и в React, где мутировать состояние нельзя.
Что важно знать про reduce, потому что там больше всего ошибок:
- начальное значение обязательно. Без него первый элемент становится аккумулятором, а на пустом массиве вызов бросает
TypeError; - колбэк обязан вернуть аккумулятор на каждой итерации. Забытый
returnпревращает его вundefinedуже на втором шаге; - через
reduceвыражаются иmap, иfilter, но читаемость от этого падает, поэтому так делают редко.
Про map есть своя типичная ошибка: его используют вместо forEach ради побочного эффекта. Тогда создаётся массив из undefined, который никому не нужен. Правило: возвращаете значение, значит map, не возвращаете, значит forEach.
Про производительность: цепочка map().filter() проходит массив дважды и создаёт промежуточный массив. На типичных размерах это несущественно, а на больших данных либо объединяют в один reduce, либо берут обычный цикл.
Полезное дополнение: у всех трёх колбэк получает вторым аргументом индекс, а третьим сам массив. И map пропускает пропуски в разреженных массивах, сохраняя их в результате.
Где спотыкаются
Вызывают reduce без начального значения.
Используют map ради побочного эффекта.
Считают, что эти методы меняют исходный массив.
Забывают вернуть аккумулятор в теле reduce.