В этом руководстве вы узнаете, как использовать перебирающие методы 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 принимает четыре аргумента:
previousValue. Значение, возвращенное предыдущим вызовом функцииcallbackFn. При первом вызовеinitialValueявляетсяpreviousValueзначением, если вы передаетеinitialValue. В противном случае его значение равноarray[0].currentValue. Значение текущего элемента массива. При первом вызове этоarray[0], если выinitialValueилиarray[1]в противном случае.currentIndex. ИндексcurrentValueв массиве. При первом вызове это0, если вы передаете initialValue или 1 в противном случае.array. Массив для цикла.
2) Аргумент начального значения
Аргумент initialValue является необязательным.
Если вы укажете initialValue, функция callbackFn инициализирует previousValue значение значением initialValue а currentValue значение — первым элементом массива при первом вызове.
Если вы не укажете initialValue, функция callbackFn инициализирует previousValue значение для первого элемента массива( array[0] ) в массиве и currentValue для второго элемента массива( array[1] ).
Следующая таблица иллюстрирует логику, когда метод reduce() выполняет callbackFn() в первый раз в соответствии с аргументом initialValue :
initialValue | previousValue | currentValue |
|---|---|---|
| Прошло | initialValue | array[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() :

