How do you implement Array.reduce from scratch?
reduce collapses an array into a single value using an accumulator.
The approach:
Start the accumulator from the initial value (or the first element if none is given).
Loop over the array.
On each step, set accumulator = callback(accumulator, element, index, array).
Return the final accumulator.
Edge case: an empty array with no initial value should throw, matching native behaviour.
Array.prototype.myReduce = function(callback, initialValue) {
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
let accumulator;
let startIndex;
if (initialValue !== undefined) {
accumulator = initialValue;
startIndex = 0;
} else {
if (this.length === 0) {
throw new TypeError('Reduce of empty array with no initial value');
}
accumulator = this[0];
startIndex = 1;
}
for (let i = startIndex; i < this.length; i++) {
accumulator = callback(accumulator, this[i], i, this);
}
return accumulator;
};
// Test
console.log([1, 2, 3, 4].myReduce((acc, n) => acc + n, 0)); // 10
console.log([1, 2, 3, 4].myReduce((acc, n) => acc + n)); // 10 (no initial: first element = 1)
console.log([1, 2, 3].myReduce((acc, n) => acc * n, 1)); // 6
// Edge case
try {
[].myReduce((acc, n) => acc + n); // TypeError!
} catch(e) {
console.log(e.message); // 'Reduce of empty array with no initial value'
}If initialValue is provided, accumulator starts with it and iteration begins at index 0. If not, accumulator starts with the first element and iteration begins at index 1.
Empty array without initialValue throws TypeError (no first element to use). Each iteration updates accumulator = callback(accumulator, element, index, array).
The initialValue handling is the key: with it, start at index 0; without it, use first element and start at index 1. Empty array + no initialValue = TypeError.
The callback signature (accumulator, element, index, array) must be correct. This is a commonly asked advanced coding question.