map, filter, and reduce appear in nearly every frontend interview. The question is rarely "do you know how to use them" — it's "implement them from scratch." Here's how to build polyfills that handle every edge case an interviewer will throw at you.
What are map(), filter(), and reduce()?
These are the three foundational higher-order array methods. Each takes a callback and iterates over the array — what differs is what they return and when the callback is invoked.
map(callback)— transforms each element and returns a new array of the same length. Every element goes through the callback; the result array mirrors the input structure. Use it when you want to change shape or type:users.map(u => u.name).filter(callback)— returns a new array containing only elements where the callback returned a truthy value. The result array is the same shape but possibly shorter. Use it to remove unwanted items:numbers.filter(n => n > 0).reduce(callback, initialValue)— accumulates the array into a single value. It's the most general of the three — bothmapandfiltercan be implemented withreduce. The callback receives an accumulator and each element, and the accumulator carries state across iterations. Use it for sums, grouping, flattening, or any operation that collapses an array.
What makes these three interview staples is that they test array iteration mechanics: sparse array holes, the optional thisArg parameter, and the fact that the callback receives (element, index, array). Building them from scratch proves you understand iteration protocols, not just the API surface.
The Problem
"Implement Array.prototype.myMap, myFilter, and myReduce from scratch. Each must match the native method's behavior: callback signature, thisArg, and sparse array handling."
Thought Process
All three follow the same skeleton:
1. Check that `this` is a valid array (or array-like)
2. Check that the callback is callable
3. Iterate over the array (skipping holes in sparse arrays)
4. Call the callback with (element, index, array)
5. Build and return the result
The differences are in step 5:
- map: return a new array of the same length with transformed values
- filter: return a new array with only elements that pass the test
- reduce: accumulate into a single value
Step 1 — myMap
Loading editor...
The i in arr check is crucial. In a sparse array like [1, , 3], index 1 doesn't exist. arr[1] would be undefined, but the native map skips it entirely. Using i in arr correctly detects holes vs. actual undefined values.
Step 2 — myFilter
Same structure, but we push matching elements instead of transforming every element:
Loading editor...
Step 3 — myReduce
reduce has one unique edge case: the initialValue parameter. If it's not provided, the first element of the array becomes the initial accumulator, and iteration starts from index 1. If the array is empty and no initialValue is given, reduce throws a TypeError.
Loading editor...
Step 4 — Edge Cases the Interviewer Will Test
Sparse arrays: [1, , 3] — all three methods must skip the hole, not treat it as undefined.
thisArg with myReduce: The native reduce passes undefined as the this for the callback. Our implementation does the same with callback.call(undefined, ...).
Callback that mutates the array: The native methods iterate based on the array's length at the time they're called, but they do read current values. If the callback pushes to the array, map and filter won't iterate the new elements. If it removes elements, the length doesn't shrink mid-iteration.
No callback provided: All three should throw a TypeError.
Step 5 — Full Solution
Loading editor...
What Interviewers Are Testing
- Callback signature — you know it's
(element, index, array), not just(element) thisArg— you pass it tocallback.call(thisArg, ...)so the callback'sthisis correct- Sparse array handling —
i in arrvs checkingarr[i] !== undefined reduceinitialValue logic — the two-path initialization: with vs without initial value- Type checking — throwing
TypeErrorwhen the callback isn't a function
Complexity
| Method | Time | Space |
|---|---|---|
myMap | O(n) | O(n) |
myFilter | O(n) | O(n) |
myReduce | O(n) | O(1) |
Interview Tips
- Write
myMapfirst and talk through it — it establishes the pattern. Then say "myFilteris almost the same but with a condition check" and write it quickly. - Don't rush
myReduce— the initialValue logic is what interviewers want to see. Say "there are two cases for the accumulator initialization" before you start coding. - Mention
i in arrout loud — "I'm usingi in arrrather than comparing toundefinedbecause sparse arrays have actual holes, and the callback should not be called for them." - Know the TypeError message — "Reduce of empty array with no initial value" is the exact wording. Reciting the correct error shows deep familiarity.