Array.prototype.map()

Builds a new array by running a function over every element of the original.

Signature
map(callbackFn)
map(callbackFn, thisArg)
  • Added in JavaScript ES5 (2009)

Parameters

ParameterTypeDescription
$callbackFnFunctionFunction run for each element. Called with (element, index, array); its return value becomes the element at that index in the new array.
$thisArgoptionalany= undefinedValue to use as this when executing callbackFn. Ignored by arrow functions, which take this from the enclosing scope.

Return value

ArrayA new array where each element is the value returned by callbackFn for the element at the same index.

Errors

Nothing of its own — any error thrown by callbackFn propagates and aborts the iteration.

map() is the workhorse for turning one array into another of the same length. It never mutates the receiver: it allocates a fresh array and fills index i with whatever your callback returned for index i. Because the length is fixed by the input, map() can never drop or add items — reach for filter() when you need fewer, and reduce() when you need a single value.

When to reach for it

  • Reshaping API records into the shape your UI expects.
  • Pulling one field out of every object.
  • Formatting numbers or dates for display.

What trips people up

The callback receives three arguments, not one, so passing a built-in that takes a second parameter misfires: ["10","10","10"].map(parseInt) gives [10, NaN, 2] because the index is handed to parseInt as the radix. Use map(Number) or an explicit arrow.

An arrow with a braced body returns undefined unless you write return, so map(x => { x.done = true }) yields an array of undefined. To return an object literal concisely, wrap it in parentheses: map(x => ({ ...x })).

Finally, ignoring the returned array is a smell — if you only want side effects, forEach() says so more clearly.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Turn an array of user records into an array of display names
  • Apply tax or currency formatting to every price in a cart
  • Convert raw API rows into the shape a chart component expects
  • Wrap each value in an object with an added computed field

Frequently asked questions

Does map() change the original array?

No — map() returns a new array and leaves the receiver alone. The catch is that it is a shallow copy: if the callback returns the same object references, mutating one of those objects still affects the original array's elements.

How do I skip elements inside map()?

You can't — map() always produces an array of the same length. Filter first (arr.filter(cond).map(fn)), or use flatMap() and return [] for the items you want dropped.

Why does my map() with async return an array of Promises?

Because an async callback returns a Promise, and map() stores whatever the callback returned. Wrap the result: const values = await Promise.all(arr.map(async (x) => …)).

More examples

The parseInt trap

The first line prints [10, NaN, 2]: map() passes the index as parseInt's second argument, so it parses in base 0, base 1 and base 2. Number takes only one argument, so it prints [10, 10, 10], as does the explicit arrow that pins the radix to 10.

Example · javascript
console.log(["10", "10", "10"].map(parseInt));
console.log(["10", "10", "10"].map(Number));
console.log(["10", "10", "10"].map((s) => parseInt(s, 10)));

Using the index, and how sparse slots survive

The first log prints ['0:a', '1:b', '2:c'], showing the second callback argument. The sparse array prints [2, <1 empty item>, 6] — the callback is never invoked for the hole, so the hole is copied through untouched, and the length stays 3.

Example · javascript
const letters = ["a", "b", "c"];
console.log(letters.map((ch, i) => `${i}:${ch}`));

const sparse = [1, , 3];
console.log(sparse.map((x) => x * 2));
console.log(sparse.map((x) => x * 2).length);

Discussion

  • Be the first to comment on this lesson.