Detailed Explanation of the Array Method Reduce in JavaScript
Description:
reduce is a higher-order function for JavaScript arrays, used to accumulate array elements into a single value via a callback function. It iterates over the array from left to right, processing each element and maintaining an intermediate result (the accumulator). The core of reduce lies in its "convergence" logic, commonly used for complex operations like summation, flattening, grouping, etc.
1. Basic Syntax of reduce
arr.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)
- callback: The function to process each element, containing the following parameters:
accumulator: The accumulated value (the return value from the previous callback or the initial value).currentValue: The current array element being processed.currentIndex(optional): The index of the current element.array(optional): The original array.
- initialValue (optional): The initial value for the accumulator. If omitted, the first element of the array is used as the initial value, and iteration starts from the second element.
2. Detailed Execution Steps
Assuming calling reduce on the array [1, 2, 3, 4]:
Case 1: No Initial Value (initialValue omitted)
const result = [1, 2, 3, 4].reduce((acc, cur) => acc + cur);
Execution Process:
- First callback:
acctakes the first element1,curtakes the second element2, returns1 + 2 = 3. - Second callback:
acc = 3,cur = 3, returns3 + 3 = 6. - Third callback:
acc = 6,cur = 4, returns6 + 4 = 10. - Final result:
10.
Note: When no initial value is provided, the number of iterations is array length - 1.
Case 2: With Initial Value (initialValue = 10)
const result = [1, 2, 3, 4].reduce((acc, cur) => acc + cur, 10);
Execution Process:
- First callback:
acc = 10,cur = 1, returns10 + 1 = 11. - Second callback:
acc = 11,cur = 2, returns11 + 2 = 13. - Third callback:
acc = 13,cur = 3, returns13 + 3 = 16. - Fourth callback:
acc = 16,cur = 4, returns16 + 4 = 20. - Final result:
20.
Key Difference: With an initial value, the number of iterations equals the array length, and the callback starts processing from the first element.
3. Common Use Cases
Case 1: Summation (Basic Usage)
const sum = [1, 2, 3].reduce((acc, cur) => acc + cur, 0); // 6
Case 2: Flattening a 2D Array
const flattened = [[1, 2], [3, 4]].reduce((acc, cur) => acc.concat(cur), []); // [1, 2, 3, 4]
Equivalent to ES2019's Array.prototype.flat().
Case 3: Counting Element Occurrences
const fruits = ['apple', 'banana', 'apple', 'orange'];
const count = fruits.reduce((acc, cur) => {
acc[cur] = (acc[cur] || 0) + 1;
return acc;
}, {}); // { apple: 2, banana: 1, orange: 1 }
Case 4: Grouping by Property
const people = [
{ name: 'Alice', age: 21 },
{ name: 'Bob', age: 21 },
{ name: 'Charlie', age: 22 }
];
const grouped = people.reduce((acc, cur) => {
const key = cur.age;
if (!acc[key]) acc[key] = [];
acc[key].push(cur);
return acc;
}, {});
// Result: { 21: [{...}, {...}], 22: [{...}] }
4. Important Notes
-
Empty array without initial value throws an error:
[].reduce((acc, cur) => acc + cur); // TypeErrorAlways specify an initial value for potentially empty arrays.
-
Accumulator type is flexible: It can be a number, array, object, etc., depending on the designed callback logic.
-
Avoid modifying the original array:
reduceshould be a pure function operation without side effects.
5. Extension: reduceRight
reduceRight has the same logic as reduce, but iterates from right to left:
const result = [1, 2, 3].reduceRight((acc, cur) => acc - cur, 0); // 0 - 3 - 2 - 1 = -6
By mastering reduce, you can replace some loop or recursive logic, making your code more functional and concise.