reduce - метод массива, который “сворачивает” массив в одно значение. Это может быть число, строка, объект или даже новый массив. В простых случаях reduce удобно использовать для суммирования и построения объекта-счетчика.
Идея reduce
reduce идет по массиву и на каждом шаге обновляет накопитель (accumulator).
const nums = [1, 2, 3, 4];
const sum = nums.reduce((acc, value) => acc + value, 0);
console.log(sum); // 10
Здесь:
acc- накопительvalue- текущий элемент0- initialValue (начальное значение накопителя)
Синтаксис
array.reduce((acc, value, index, array) => {
return nextAcc;
}, initialValue);
acc- накопительvalue- текущий элементindex,array- дополнительные параметры (не всегда нужны)initialValue- начальное значение накопителя
Практичное правило: initialValue лучше задавать явно.
Пример 1: сумма чисел
const nums = [10, 20, 30];
const sum = nums.reduce((acc, n) => acc + n, 0);
console.log(sum); // 60
Пример 2: произведение
const nums = [2, 3, 4];
const product = nums.reduce((acc, n) => acc * n, 1);
console.log(product); // 24
Начальное значение 1 важно: умножение на 1 не меняет результат.
Пример 3: максимум
const nums = [5, 7, 2, 10, 3];
const max = nums.reduce((acc, n) => (n > acc ? n : acc), -Infinity);
console.log(max); // 10
Пример 4: объект-счетчик
Частая задача - посчитать, сколько раз встречается каждое значение.
const letters = ["a", "b", "a", "c", "b", "a"];
const counts = letters.reduce((acc, letter) => {
const current = acc[letter] || 0;
acc[letter] = current + 1;
return acc;
}, {});
console.log(counts); // { a: 3, b: 2, c: 1 }
Здесь накопитель - объект {}.
Объект-счетчик с числами
const nums = [1, 2, 2, 3, 3, 3];
const counts = nums.reduce((acc, n) => {
const key = String(n);
acc[key] = (acc[key] || 0) + 1;
return acc;
}, {});
console.log(counts); // { "1": 1, "2": 2, "3": 3 }
Ключи объекта - строки, поэтому String(n) делает намерение явным.
Почему initialValue важно
Если initialValue не передать, reduce возьмет первый элемент массива как начальный acc, а перебор начнется со второго элемента. Это может быть неожиданно и ломает код на пустых массивах.
Пример, который выглядит нормально, но опасен:
const nums = [10, 20, 30];
const sum = nums.reduce((acc, n) => acc + n);
console.log(sum); // 60
Если массив пустой, будет ошибка:
const nums = [];
try {
const sum = nums.reduce((acc, n) => acc + n);
console.log(sum);
} catch (e) {
console.log(e.name); // "TypeError"
}
С initialValue пустой массив обрабатывается корректно:
const nums = [];
const sum = nums.reduce((acc, n) => acc + n, 0);
console.log(sum); // 0
reduce и читаемость
reduce мощный, но его легко сделать слишком сложным. Практичное правило: использовать reduce, когда логика действительно “сводит к одному значению”. Если нужно просто преобразовать или отобрать элементы, обычно подходят map и filter.
Частые ошибки
1) Забыли вернуть acc
Колбэк reduce должен возвращать обновленный накопитель.
const nums = [1, 2, 3];
const sum = nums.reduce((acc, n) => {
acc + n;
return acc;
}, 0);
console.log(sum); // 0
Правильно:
const nums = [1, 2, 3];
const sum = nums.reduce((acc, n) => acc + n, 0);
console.log(sum); // 6
2) Неподходящее initialValue
Для суммы - 0, для произведения - 1, для счетчика - {}.
const nums = [2, 3];
const product = nums.reduce((acc, n) => acc * n, 0);
console.log(product); // 0
Что стоит запомнить
reduceсводит массив к одному значению.- Накопитель (acc) обновляется на каждом шаге и возвращается из колбэка.
initialValueлучше задавать явно: это делает код стабильнее и понятнее.- Простейшие кейсы: сумма, произведение, максимум, объект-счетчик.