Ситуация: мы пишем скрипт для веб-интерфейса аналитики, который обрабатывает данные прямо на стороне пользователя. Чтобы отфильтровать ненужные нам в этот момент данные, используем функцию filter()
, а затем применяем функцию reduce()
, чтобы посчитать сумму всех оставшихся элементов массива.
const ints = [0, -1, -2, -3, -4, -5];
ints
.filter((x) => x > 0) // фильтруем массив
.reduce((x, y) => x + y); // находим сумму всех его элементов
Всё написано правильно, но при запуске мы почему-то получаем ошибку:
❌ TypeError: Reduce of empty array with no initial value
Что это значит: мы попытались с помощью функции reduce()
обработать массив, у которого функция не смогла взять начальное значение для своих вычислений.
Когда встречается: в ситуациях, когда функции просто неоткуда взять начальное значение. В нашем случае — из-за того, что массив оказался пуст после фильтра.
Что делать с ошибкой TypeError: Reduce of empty array with no initial value
Чтобы разобраться с этой ошибкой, нужно немного подробнее остановиться на функции reduce()
. Для её работы нужны такие параметры вот в таком порядке:
- Аккумулятор — результат предыдущего вызова функции, в нём хранятся результаты прошлых вычислений. Обычно этот параметр обязательно указывается при вызове функции, остальные можно опускать.
- Очередной элемент массива — то, с чем функция будет работать на каждом шаге.
- Позиция этого элемента.
- Сам исходный массив.
Так вот, в нашем примере вызов функции выглядит так:
.reduce((x, y) => x + y); // находим сумму всех его элементов
Это значит, что переменная x — это аккумулятор, а y — очередной элемент массива. Дальше идёт описание того, что нужно сделать: прибавить значение элемента массива к тому, что уже посчитано (и хранится в аккумуляторе).
Но так как у нас после фильтра массив оказался пустым (мы убрали все элементы меньше нуля, и в нём ничего не осталось), то функция работает так:
- Запускается.
- Пробует взять первый элемент массива.
- Не находит его и понимает, что ей нужно вернуть какое-то значение.
- Это значение — результат предыдущих вычислений.
- Предыдущих вычислений не было.
- Функция тогда не понимает, что ей нужно возвращать, и падает с ошибкой.
Поэтому, чтобы исправить эту ошибку, нам нужно просто добавить в вызов начальное значение инициала (оно же — результат предыдущей работы, который отправится в аккумулятор). Зная это, немного правим код, который уже сможет справиться с пустым массивом: добавляем ноль в качестве стартового значения вычислений.
const ints = [0, -1, -2, -3, -4, -5];
ints
.filter((x) => x > 0) // фильтруем массив
.reduce((x, y) => x + y, 0); // находим сумму всех его элементов