map() creates a new array by running a function on every item of an old one. The original is not changed, and the new array always has the same length.
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(n => n * 2);
console.log(doubled); // → [2, 4, 6, 8]
console.log(numbers); // → [1, 2, 3, 4]
Read it as: “for each n, give me n * 2“.
The callback arguments
The callback receives the item, its index, and the whole array. You usually only need the first one or two.
const letters = ["a", "b", "c"];
const labelled = letters.map((letter, index) => `${index + 1}. ${letter}`);
console.log(labelled); // → ["1. a", "2. b", "3. c"]
Mapping objects
This is where map earns its place: reshape data.
const users = [
{ firstName: "Maya", lastName: "Rao" },
{ firstName: "Arjun", lastName: "Nair" }
];
const names = users.map(user => `${user.firstName} ${user.lastName}`);
console.log(names); // → ["Maya Rao", "Arjun Nair"]
const cards = users.map(user => ({ title: user.firstName, id: user.lastName.toLowerCase() }));
console.log(cards);
Building HTML
<ul id="list"></ul>
<script>
const products = [
{ name: "Notebook", price: 4 },
{ name: "Pen", price: 1.5 }
];
document.querySelector("#list").innerHTML = products
.map(product => `<li>${product.name} - $${product.price}</li>`)
.join("");
</script>
(With data from users, avoid innerHTML, see textContent vs innerHTML.)
map vs forEach
forEach only runs code for each item and returns nothing. map returns a new array. If you do not use the returned array, you probably want forEach or a for...of loop.
A classic gotcha
console.log(["1", "2", "3"].map(parseInt)); // → [1, NaN, NaN]
map passes (item, index), and parseInt treats the second argument as the radix. Write it out: .map(s => parseInt(s, 10)) or use .map(Number).
Forgetting to return
{ }, you must write return. arr.map(x => { x * 2 }) returns an array of undefined.