Array.prototype.map()

One in, one out — the result always has the same length as the input. If you are dropping elements you want filter; if you are returning nothing you want forEach.

Array methodES5 (2009)Live demo
Common call
items.map(x => x * 2)
Returns
a new array, same length, original untouched
Replaces
a for loop that pushes into a result array
Watch out
forgetting to return from the callback gives an array of undefined
array.map(callback[, thisArg])
→ Array

Demo

Live evaluation
Try:
Inputs
itemsnumber[]numbers, comma separated
factornumbermultiplier
Output
[1, 2, 3].map(x => x * 2)
[2, 4, 6]

Every element goes through the callback and the results form a new array of exactly the same length — three in, three out, always. The empty case returns an empty array rather than an error. Note that the original array is untouched: map is one of the non-mutating Array methods, which is the dividing line that causes most Array confusion.

Parameters

NameTypeRequiredDescription
callbackFunctionyesCalled as callback(element, index, array) for every element. Its return value becomes the corresponding element of the new array.
thisArganyno (undefined)Value of `this` inside the callback. Ignored for arrow functions, which take `this` from the enclosing scope.

Return value

Array — A NEW array of the same length, holding whatever the callback returned for each element. The original array is never modified.

Common patterns

Extract one field from each object
The single most common use.
const names = users.map(u => u.name);
Convert types across an array
Parsing a row of strings into numbers.
const nums = ['1', '2', '3'].map(Number);
Use the index
The callback receives (element, index, array).
const numbered = items.map((x, i) => `${i + 1}. ${x}`);

Examples

1. Double each
[1, 2, 3].map(x => x * 2)
Returns
[2, 4, 6]
2. Extract a field
[{n: 1}, {n: 2}].map(o => o.n)
Returns
[1, 2]
3. Empty stays empty
[].map(x => x * 2)
Returns
[]
4. Original untouched
const a = [1, 2]; a.map(x => x * 2); a
Returns
[1, 2]
5. Missing return
[1, 2].map(x => { x * 2 })
Returns
[undefined, undefined]
6. parseInt trap
['1', '2', '3'].map(parseInt)
Returns
[1, NaN, NaN]

Pitfalls

1. A braced callback with no return gives undefined
An arrow function with braces needs an explicit return. Without it every element becomes undefined — and because the array is still the right length, the mistake often survives until something downstream breaks.
No return
[1, 2].map(x => { x * 2 })
[undefined, undefined]
Return it
[1, 2].map(x => x * 2)
[2, 4]
2. map(parseInt) passes the index as the radix
The classic. map calls the callback with three arguments, and parseInt takes (string, radix) — so the index becomes the radix. Index 1 is an invalid radix and index 2 parses "3" in base 2.
Index becomes radix
['1', '2', '3'].map(parseInt)
[1, NaN, NaN]
Wrap it
['1', '2', '3'].map(x => parseInt(x, 10))
[1, 2, 3]
3. Using map when you meant forEach
If the callback returns nothing, map builds a whole array of undefined and throws it away. It is not wrong so much as wasteful and misleading to a reader — forEach states the intent.
Array discarded
items.map(x => console.log(x));
builds [undefined, ...] for nothing
Use forEach
items.forEach(x => console.log(x));
no array built
4. map cannot drop elements
The output length always equals the input length. Returning undefined for unwanted elements leaves holes rather than removing them — filter is the tool that changes the length.
Leaves undefined
[1, 2, 3].map(x => x > 1 ? x : undefined)
[undefined, 2, 3]
Filter first
[1, 2, 3].filter(x => x > 1)
[2, 3]

When to use

Use it
  • Transforming every element into something else
  • Extracting one field from an array of objects
  • Converting types across a whole array
  • Anywhere a for loop would just push into a result array
Reach for something else
  • You need fewer elements out than in → filter
  • The callback returns nothing → forEach
  • You are reducing to a single value → reduce
  • You need to stop early → a for...of loop with break

Notes

Complexity
O(n) — the callback runs once per element
Return
A new array; the original is never modified
CPython impl
V8: Builtins-array-map.tq — the fast path requires a packed array
Memory
Allocates a second array the same length as the input
Thread-safe
Single-threaded; a callback that mutates the source array sees undefined behaviour for unvisited indices

FAQ

Because map calls the callback with (element, index, array) and parseInt takes (string, radix). The index arrives as the radix: index 0 means "auto", index 1 is an invalid radix giving NaN, index 2 parses in binary. Wrap the call so only the element is passed.

['1', '2', '3'].map(x => parseInt(x, 10))
// [1, 2, 3]

History

ES5
Array.prototype.map standardised in 2009, having shipped in JavaScript 1.6 (2005).
ES2015
Arrow functions made the common one-line callback dramatically shorter.