Методы Array reduce() и reduceRight() в JavaScript

В этом руководстве вы узнаете, как использовать перебирающие методы JavaScript Array reduce() и reduceRight() для преобразования и сокращения массива до значения.

Предположим, что у вас есть массив чисел, например:

let numbers = [1, 2, 3];

и вы хотите вычислить общее количество элементов массива.

Как правило, вы используете цикл for в Javascript для перебора элементов и их добавления, как показано в следующем примере:

let numbers = [1, 2, 3];

let sum = 0;
for(let i = 0; i < numbers.length; i++) {
    sum += numbers[i];
}

console.log(sum);

Выход:

6

Скрипт прост и понятен:

  • Сначала объявите массив из трех чисел 1, 2 и 3.
  • Во-вторых, объявите переменную sum и установите ее значение равным нулю.
  • В-третьих, в цикле for добавьте элементы массива numbers к переменной sum. После цикла значение переменной sum равно 6.

Что мы сделали, так это преобразовали массив в значение.

Array.prototype позволяет уменьшить массив до одного значения с помощью метода reduce() следующим образом:

let numbers = [1, 2, 3];
let sum = numbers.reduce(function(previousValue, currentValue) {
    return previousValue + currentValue;
});

console.log(sum);

Это довольно просто, не так ли?

Давайте подробно рассмотрим метод reduce().

Подробное описание

Ниже показан синтаксис метода reduce() :

array.reduce(callbackFn [, initialValue])

Метод reduce() принимает два аргумента:

  • Функция обратного вызова callbackFn. Эту функцию часто называют редуктором.
  • Необязательное начальное значение.

Метод вызывает callbackFn() для каждого элемента массива.

Функция reducer() возвращает значение, полученное в результате выполнения callbackFn до завершения всего массива.

1) Аргумент функции callbackFn()

Функция callbackFn имеет следующий синтаксис:

function callbackFn(previousValue, currentValue, currentIndex, array) { /**/}

Функция callbackFn принимает четыре аргумента:

  1. previousValue. Значение, возвращенное предыдущим вызовом функции callbackFn. При первом вызове initialValue является previousValue значением, если вы передаете initialValue. В противном случае его значение равно array[0].
  2. currentValue. Значение текущего элемента массива. При первом вызове это array[0], если вы initialValue или array[1] в противном случае.
  3. currentIndex. Индекс currentValue в массиве. При первом вызове это 0, если вы передаете initialValue или 1 в противном случае.
  4. array. Массив для цикла.

2) Аргумент начального значения

Аргумент initialValue является необязательным.

Если вы укажете initialValue, функция callbackFn инициализирует previousValue значение значением initialValue а currentValue значение — первым элементом массива при первом вызове.

Если вы не укажете initialValue, функция callbackFn инициализирует previousValue значение для первого элемента массива( array[0] ) в массиве и currentValue для второго элемента массива( array[1] ).

Следующая таблица иллюстрирует логику, когда метод reduce() выполняет callbackFn() в первый раз в соответствии с аргументом initialValue :

initialValuepreviousValuecurrentValue
ПрошлоinitialValuearray[0]
Не прошлоarray[0]array[1]

В следующем примере показан ход выполнения функции reduce() с initialValue значением, равным 100:

let numbers = [1, 2, 3];

function getOrdinalSuffix(i) {
  let j = i % 10, k = i % 100;
  if (j == 1 && k != 11) return i + 'st';
  if (j == 2 && k != 12) return i + 'nd';  
  if (j == 3 && k != 13) return i + 'rd';
  return i + 'th';
}

let call = 1;
let sum = numbers.reduce(function (previousValue, currentValue, currentIndex, array) {
    let result = previousValue + currentValue;

    // show the 1st call, 2nd call, etc.
    console.log(`${getOrdinalSuffix(call)} call`);
    call++;

    // show the immediate values
    console.table({ previousValue, currentValue, currentIndex, result });

    return result;
},100);

console.log(`Result: ${sum}`);

Выход:

1st call
┌───────────────┬────────┐
│    (index)    │ Values │
├───────────────┼────────┤
│ previousValue │  100   │
│ currentValue  │   1    │
│ currentIndex  │   0    │
│    result     │  101   │
└───────────────┴────────┘
2nd call
┌───────────────┬────────┐
│    (index)    │ Values │
├───────────────┼────────┤
│ previousValue │  101   │
│ currentValue  │   2    │
│ currentIndex  │   1    │
│    result     │  103   │
└───────────────┴────────┘
3rd call
┌───────────────┬────────┐
│    (index)    │ Values │
├───────────────┼────────┤
│ previousValue │  103   │
│ currentValue  │   3    │
│ currentIndex  │   2    │
│    result     │  106   │
└───────────────┴────────┘
Result: 106

А следующий пример иллюстрирует метод reduce() без аргумента initialValue :

1st call
┌───────────────┬────────┐
│   (index)    │ Values │
├───────────────┼────────┤
│ previousValue │   1    │
│ currentValue  │   2    │
│ currentIndex  │   1    │
│    result     │   3    │
└───────────────┴────────┘
2nd call
┌───────────────┬────────┐
│   (index)    │ Values │
├───────────────┼────────┤
│ previousValue │   3    │
│ currentValue  │   3    │
│ currentIndex  │   2    │
│    result     │   6    │
└───────────────┴────────┘
Result: 6

Дополнительные примеры

Предположим, у вас есть следующий массив объектов товаров shoppingCart :

let shoppingCart = [
  {
    product: 'phone',
    qty: 1,
    price: 500,
  },
  {
    product: 'Screen Protector',
    qty: 1,
    price: 10,
  },
  {
    product: 'Memory Card',
    qty: 2,
    price: 20,
  },
];

Чтобы рассчитать общее количество продуктов в корзине, вы можете использовать метод reduce(), например:

let total = shoppingCart.reduce(function(previousValue, currentValue) {
  return previousValue + currentValue.qty * currentValue.price;
}, 0);

Выход:

550

Обратите внимание, что в этом примере мы передали аргумент initialValue reduce().

Если бы мы этого не сделали, метод reduce() принял бы первый элемент массива shoppingCart, который является объектом, в качестве начального значения и выполнил бы вычисление для этого объекта. Следовательно, это приведет к неправильному результату.

Метод reduceRight()

Метод reduceRight() работает так же, как и метод reduce(), но в обратном направлении.

Метод начинается с первого элемента и перемещается к последнему, тогда как метод reduceRight() начинается с последнего элемента и перемещается назад к первому.

Пример:

let numbers = [1, 2, 3];

let sum = numbers.reduceRight(function(previousValue, currentValue) {
  console.log({ previousValue, currentValue });
  return previousValue + currentValue;
});

console.log(`Result:${sum}`);

Выход

{ previousValue: 3, currentValue: 2 }
{ previousValue: 5, currentValue: 1 }
Result:6

На следующем рисунке показана разница между методами reduce() и reduceRight() :

Разница между методами reduce() и reduceRight()

Рейтинг
( Пока оценок нет )
Александр Русаков / автор статьи
Программист, разработчик, 12 лет опыта работы в крупных компаниях. Быстро освоил typescript, делюсь своими знаниями на страницах этого сайта.
Загрузка ...
JavaScript и TypeScript