Learn JavaScript

reduceRight() - метод для сворачивания массива справа налево в JavaScript

reduceRight() проходит по массиву справа налево и сводит его к одному итоговому значению.

По идее это тот же reduce(), только обход идёт не от начала массива к концу, а в обратную сторону.

Синтаксис

array.reduceRight(callback)
array.reduceRight(callback, initialValue)

callback - функция, которая вызывается для каждого элемента массива.

initialValue - начальное значение аккумулятора.

Что делает reduceRight()

Во время работы reduceRight() на каждом шаге берёт текущее накопленное значение и текущий элемент массива, а потом возвращает новое накопленное значение.

const letters = ["a", "b", "c"];

const result = letters.reduceRight((accumulator, value) => {
  return accumulator + value;
}, "");

console.log(result); // "cba"

Здесь хорошо видно главное отличие: массив обходится с конца.

accumulator и currentValue

Чаще всего callback выглядит так:

array.reduceRight((accumulator, currentValue) => {
  // ...
}, initialValue)
  • accumulator - накопленное значение с предыдущего шага
  • currentValue - текущий элемент массива

Логика здесь такая же, как у reduce(). Меняется только направление обхода.

Что возвращает reduceRight()

reduceRight() возвращает одно итоговое значение.

const numbers = [1, 2, 3];

const result = numbers.reduceRight((acc, value) => acc + value, 0);

console.log(result); // 6

Результат может быть числом, строкой, объектом, массивом или любым другим значением.

Почему направление важно

Для суммы порядок обычно не важен:

const numbers = [1, 2, 3];

console.log(numbers.reduce((acc, value) => acc + value, 0));      // 6
console.log(numbers.reduceRight((acc, value) => acc + value, 0)); // 6

Но для строк или других операций разница уже заметна:

const letters = ["a", "b", "c"];

console.log(letters.reduce((acc, value) => acc + value, ""));      // "abc"
console.log(letters.reduceRight((acc, value) => acc + value, "")); // "cba"

Именно поэтому reduceRight() нужен не всегда, а только там, где порядок действительно влияет на результат.

Зачем нужен initialValue

initialValue задаёт стартовое значение аккумулятора.

const numbers = [1, 2, 3];

const result = numbers.reduceRight((acc, value) => acc + value, 0);

console.log(result); // 6

Это самый понятный и безопасный вариант использования метода.

Что будет без initialValue

Если initialValue не передать, reduceRight() возьмёт последний элемент массива как начальный аккумулятор, а обход начнётся с предпоследнего элемента.

const numbers = [1, 2, 3];

const result = numbers.reduceRight((acc, value) => acc + value);

console.log(result); // 6

Это работает, но может запутывать.

Поэтому в обычном коде initialValue часто передают явно.

Пустой массив и ошибка

Если массив пустой и initialValue не указан, reduceRight() выбросит ошибку.

const numbers = [];

// numbers.reduceRight((acc, value) => acc + value); // TypeError

Если передать начальное значение, всё будет нормально:

const numbers = [];

const result = numbers.reduceRight((acc, value) => acc + value, 0);

console.log(result); // 0

reduceRight() и reduce()

Эти методы делают одно и то же по смыслу, но обходят массив в разном направлении.

const letters = ["a", "b", "c"];

console.log(letters.reduce((acc, value) => acc + value, ""));      // "abc"
console.log(letters.reduceRight((acc, value) => acc + value, "")); // "cba"

reduce() идёт слева направо.

reduceRight() идёт справа налево.

reduceRight() не меняет исходный массив

Сам метод не изменяет массив.

const numbers = [1, 2, 3];
const result = numbers.reduceRight((acc, value) => acc + value, 0);

console.log(numbers); // [1, 2, 3]
console.log(result);  // 6

Но внутри callback можно менять внешние данные, если так написать.

Аргументы callback

Callback в reduceRight() может получать до четырёх аргументов:

array.reduceRight((accumulator, currentValue, index, array) => {
  // ...
}, initialValue)
  • accumulator - накопленное значение
  • currentValue - текущий элемент
  • index - индекс текущего элемента
  • array - сам исходный массив

Обычно в коде чаще всего используют первые два.

Пустые слоты

reduceRight() пропускает пустые слоты массива.

const arr = Array(3);

const result = arr.reduceRight((acc, value) => acc + 1, 0);

console.log(result); // 0

Callback здесь не вызывается для пустых слотов.

Когда это полезно

reduceRight() удобно использовать, когда:

  • порядок обхода важен
  • нужно обработать массив с конца
  • нужно собрать строку, массив или другое значение именно справа налево

Пример:

const parts = ["world", " ", "hello"];

const text = parts.reduceRight((acc, value) => acc + value, "");

console.log(text); // "hello world"

Частые ошибки

Думать, что reduceRight() делает что-то совсем другое, чем reduce()

const numbers = [1, 2, 3];

const result = numbers.reduceRight((acc, value) => acc + value, 0);

Идея у метода та же самая. Главное отличие только в направлении обхода.

Забывать initialValue

const numbers = [];

// numbers.reduceRight((acc, value) => acc + value); // TypeError

На пустом массиве без начального значения метод упадёт.

Не возвращать accumulator

const numbers = [1, 2, 3];

const result = numbers.reduceRight((acc, value) => {
  acc + value;
}, 0);

console.log(result); // undefined

Если callback ничего не возвращает, следующий шаг получит undefined.

Быстрая памятка

  • reduceRight() сводит массив к одному значению
  • обход идёт справа налево
  • ключевая идея метода - accumulator
  • initialValue лучше передавать явно
  • reduceRight() не меняет исходный массив

Коротко

reduceRight() - это версия reduce(), которая работает с конца массива. Главное, что стоит запомнить: метод полезен тогда, когда порядок обхода влияет на результат, а по остальной логике он очень похож на обычный reduce().