Polyfill: map()
Prompt
Imagine the JavaScript array method .map() does not exist. Implement a myMap method on Array.prototype that works like the native .map().
Playground
map is like forEach but it collects the return value
of each callback call into a new array. Create an empty
array, loop through this, push the callback result for
each element, and return the new array.
The callback receives three arguments: callback(element, index, array). Use a regular for loop (not for...of)
so you have access to the index.
Solution
Explanation
map is almost identical to forEach. The only difference is that map collects the return value of each callback into a new array and returns it.
// forEach: just calls the function, returns nothing
// map: calls the function, collects results into a new array
const result = [];
for (let i = 0; i < this.length; i++) {
result.push(callback(this[i], i, this));
}
return result;For each element, we call the callback with (element, index, array) and push whatever it returns into result. At the end, we return result. The original array is never modified.
The returned array always has the same length as the original. If your callback doesn't explicitly return something, JavaScript returns undefined by default, so you'd get an array full of undefined values. That's not a bug in our polyfill, that's how the native .map() works too.
map vs forEach
If you're not using the returned array, you should use
forEach instead of map. Using map just for side
effects (like logging) is considered bad practice because
you're creating an array that gets thrown away.
Why not for...of?
You might be tempted to use for (const element of this)
since it's cleaner. But for...of only gives you the
element, not the index. The native .map() passes
(element, index, array) to the callback, so we need a
regular for loop to have access to i.
When do you use map?
- Data transformation: converting an array of objects into a different shape (e.g., extracting just the names from a list of users)
- Rendering lists in React:
items.map(item => <Item key={item.id} {...item} />) - Formatting data: converting numbers to strings, adding prefixes, changing date formats
- Deriving new values: computing new values from existing ones without modifying the original