По моим собственным словам, reduce
— это метод массива, который используется для «сведения» всех значений в массиве к одному значению. Отличным примером этого является суммирование всех чисел в массиве.
Вот более официальное определение reduce
:
Метод
reduce()
выполняет функцию reducer (предоставленную вами) для каждого элемента массива, в результате чего получается одно выходное значение. — МДН
Итак, если у нас есть какой-то массив arr
, мы можем вызвать для него reduce
и передать функцию callback
, которая будет выполняться для каждого элемента в массиве и будет возвращать одно значение result
:
const result = arr.reduce(callback)
При желании вы можете передать начальное значение initialVal
в reduce
. Если начальное значение не передается, в качестве начального значения используется первый элемент массива.
const result = arr.reduce(callback, initialVal)
Функция обратного вызова принимает 4 аргумента:
accumulator
— это накопление возвращаемых значений обратного вызоваcurrentVal
— текущее обрабатываемое значениеindex
— текущий индекс обрабатываемого значения (необязательно)arr
— это массив, к которому был вызванreduce
(необязательно)
Давайте посмотрим на пример, использующий преобразование в сумму чисел в массиве:
const arr = [1,2,3,4] const result = arr.reduce((accumulator, currVal) => accumulator + currVal) console.log(result) // => 10
Здесь мы вызываем reduce
для массива arr
, мы используем функцию обратного вызова (accumulator, currVal) => accumulator + currVal
и используем начальное значение по умолчанию. Наша функция обратного вызова добавляет каждый элемент (currVal
) к нашей текущей сумме (accumulator
).
Давайте рассмотрим, как именно это работает:
- Поскольку мы не передали
initialVal
, первый элемент массива используется какinitialVal
и не используется в функции обратного вызова. Итак, нашеaccumulator
начинается с 1 - Первое значение, проходящее через функцию обратного вызова, равно 2, и с нашим
accumulator
равным 1, 1+2=3, поэтому нашеaccumulator
теперь равно 3. - Следующее значение равно 3, 3+3=6, поэтому наше
accumulator
теперь равно 6. - И, наконец, наше последнее значение равно 4, 6+4=10, поэтому наше
accumulator
равно 10. - Мы возвращаем 10 из
reduce
, и 10 сохраняется в переменнойresult
.
Если для вас это звучит очень похоже на этот код, вы не ошиблись:
const arr = [1,2,3,4] let sum = 0 for (let i=0; i<arr.length; i++) { sum += arr[i] } console.log(sum) // => 10
Цикл for также выполняет суммирование значений в массиве, reduce
— это, пожалуй, более простой и чистый способ сделать это.
Если мы посмотрим на тот же пример, но включим initialVal
из 5:
const arr = [1,2,3,4] const result = arr.reduce((accumulator, currVal) => accumulator + currVal, 5) console.log(result) // => 15
Мы получаем тот же результат, что и выше, плюс 5. Это потому, что происходит та же логика, мы просто начинаем accumulator
с 5 вместо первого значения в массиве.
Вы можете сделать гораздо больше с reduce
, чем с суммированием чисел, и вот пример, демонстрирующий другой вариант использования:
const arr = ['cookie', 'cake', 'ice cream', 'cookie', 'brownie', 'cookie', 'ice cream', 'fruit', 'ice cream', 'cookie', 'cake'] const obj = arr.reduce((accumulator, currVal) => { if (accumulator.hasOwnProperty(currVal)) { accumulator[currVal]++ } else { accumulator[currVal] = 1 } return accumulator }, {}) console.log(obj) // => { 'cookie': 4, 'cake': 2, 'ice cream': 3, 'brownie': 1, 'fruit': 1 }
Мы только что использовали reduce
, чтобы подсчитать, сколько раз каждый элемент появляется в массиве! Разберем приведенный выше код:
- Мы передали пустой объект
{}
в качестве начального значения. - Для каждого элемента в массиве проверьте, является ли этот элемент ключом в нашем объекте, используя
hasOwnProperty
- Если это так, увеличьте значение, которое является подсчетом того, сколько раз оно находится в массиве.
- Если это не так, добавьте элемент в качестве ключа к объекту и установите значение 1
- После того, как мы просмотрим каждый элемент массива, верните
accumulator
и сохраните его в переменнойobj
.
Удачного сокращения!