Array.prototype.reduce Polyfill
ArraysPolyfill
Implement Array.prototype.myReduce that behaves identically to the native reduce.
Function Signature:
Array.prototype.myReduce = function (callback, initialValue) { }
Requirements:
- Throw
TypeErrorifcallbackis not a function - When
initialValueis provided: start accumulator atinitialValue, iterate from index 0 - When
initialValueis not provided: first real element becomes accumulator, iterate from index 1 - Calling on an empty array with no
initialValuemust throwTypeError - Skip holes in sparse arrays
Examples
Example 1
Input
[1, 2, 3, 4].myReduce((acc, cur) => acc + cur, 0)Output
10Explanation
Starts at 0, folds left: 0+1=1, 1+2=3, 3+3=6, 6+4=10.
Example 2
Input
[1, 2, 3].myReduce((acc, cur) => acc + cur)Output
6Explanation
No initial value: first element (1) is the accumulator, then 1+2=3, 3+3=6.
Example 3
Input
[].myReduce((acc, cur) => acc + cur)Output
TypeError: Reduce of empty array with no initial valueExplanation
Empty array with no initial value must throw.
Constraints
- Use `arguments.length >= 2` to detect whether initialValue was passed — not `=== undefined`
- Do not use the native Array.prototype.reduce internally
Notes
- `undefined` is a valid initial value a caller might pass intentionally
Hints
Editorial: Array.prototype.reduce Polyfill
Implementing Array.prototype.reduce from scratch
reduce folds an array into a single value. The callback receives (accumulator, currentValue, index, array). All the complexity lives in handling the optional initialValue.
What the interviewer checks
Do you handle the case where no initialValue is passed? When there is no initial value:
- The first element becomes the accumulator
- Iteration starts at index 1
- Calling reduce on an empty array must throw
TypeError
Implementation
Array.prototype.myReduce = function (callback, initialValue) { if (typeof callback !== "function") { throw new TypeError(callback + " is not a function"); } const hasInitial = arguments.length >= 2; let acc = initialValue; let startIndex = 0; if (!hasInitial) { // find the first real element (skip holes) while (startIndex < this.length && !(startIndex in this)) { startIndex++; } if (startIndex >= this.length) { throw new TypeError("Reduce of empty array with no initial value"); } acc = this[startIndex]; startIndex++; } for (let i = startIndex; i < this.length; i++) { if (i in this) { acc = callback(acc, this[i], i, this); } } return acc; };
The critical detail
Use arguments.length >= 2 to detect whether initialValue was passed — not initialValue === undefined.
undefined is a valid initial value that a caller might pass intentionally:
[1, 2, 3].myReduce((acc, x) => acc, undefined); // initialValue IS provided — acc starts as undefined
Checking === undefined would incorrectly treat this as "no initial value provided".
Edge cases to mention
- Empty array + no initial value → throws
TypeError - Empty array + initial value → returns initial value unchanged
- Single element + no initial value → returns that element, callback is never called
- Holes in sparse arrays are skipped in both the initial-value search and the main loop
</>JavaScript
Loading editor…
Test Result
Run your code, or Submit to test it