JavaScript BasicsFeatured
JavaScript map() Method: Complete Guide with Examples
Master the JavaScript array map() method. Learn how to transform arrays, work with objects, handle async operations, and avoid common pitfalls.
By JavaScriptDoc Team•
maparray methodsfunctional programmingjavascripttransformation
JavaScript map() Method: Complete Guide with Examples
The map()
method is one of the most powerful and frequently used array methods in JavaScript. It creates a new array by transforming each element of an existing array through a function you provide.
Understanding map()
The map()
method calls a function on every element in an array and returns a new array containing the results.
// Basic syntax
const newArray = array.map(function (element, index, array) {
// Return transformed element
return transformedElement;
});
// Arrow function syntax
const newArray = array.map((element, index, array) => transformedElement);
Key Characteristics
- Returns a new array - Original array is not modified
- Same length - Result array has same length as original
- Transforms each element - Applies function to every element
- Maintains order - Elements stay in same order
Basic Examples
Transforming Numbers
// Double each number
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(numbers); // [1, 2, 3, 4, 5] - unchanged
// Square each number
const squared = numbers.map((num) => num ** 2);
console.log(squared); // [1, 4, 9, 16, 25]
// Convert to string
const strings = numbers.map((num) => num.toString());
console.log(strings); // ['1', '2', '3', '4', '5']
// More complex transformation
const processed = numbers.map((num) => ({
original: num,
doubled: num * 2,
squared: num ** 2,
isEven: num % 2 === 0,
}));
Transforming Strings
const words = ['hello', 'world', 'javascript'];
// Uppercase
const uppercase = words.map((word) => word.toUpperCase());
console.log(uppercase); // ['HELLO', 'WORLD', 'JAVASCRIPT']
// Get lengths
const lengths = words.map((word) => word.length);
console.log(lengths); // [5, 5, 10]
// Capitalize first letter
const capitalized = words.map(
(word) => word.charAt(0).toUpperCase() + word.slice(1)
);
console.log(capitalized); // ['Hello', 'World', 'Javascript']
// Add prefix/suffix
const decorated = words.map((word) => `*${word}*`);
console.log(decorated); // ['*hello*', '*world*', '*javascript*']
Working with Objects
Extracting Properties
const users = [
{ id: 1, name: 'John', age: 30 },
{ id: 2, name: 'Jane', age: 25 },
{ id: 3, name: 'Bob', age: 35 },
];
// Extract names
const names = users.map((user) => user.name);
console.log(names); // ['John', 'Jane', 'Bob']
// Extract multiple properties
const userInfo = users.map((user) => ({
name: user.name,
age: user.age,
}));
// Create new structure
const userCards = users.map((user) => ({
displayName: `${user.name} (${user.age})`,
userId: user.id,
isAdult: user.age >= 18,
}));
Transforming Object Arrays
const products = [
{ name: 'Laptop', price: 999, category: 'Electronics' },
{ name: 'Shirt', price: 29, category: 'Clothing' },
{ name: 'Book', price: 15, category: 'Education' },
];
// Apply discount
const discounted = products.map((product) => ({
...product,
price: product.price * 0.9,
discountApplied: true,
}));
// Add calculated fields
const enriched = products.map((product) => ({
...product,
priceWithTax: product.price * 1.2,
displayPrice: `$${product.price.toFixed(2)}`,
}));
// Transform to different format
const options = products.map((product) => ({
value: product.name.toLowerCase().replace(' ', '-'),
label: product.name,
data: product,
}));
Using Index and Array Parameters
const letters = ['a', 'b', 'c', 'd'];
// Using index
const indexed = letters.map((letter, index) => `${index}: ${letter}`);
console.log(indexed); // ['0: a', '1: b', '2: c', '3: d']
// Using array parameter
const withNext = letters.map((letter, index, array) => {
const next = array[index + 1] || 'end';
return `${letter} -> ${next}`;
});
console.log(withNext); // ['a -> b', 'b -> c', 'c -> d', 'd -> end']
// Creating numbered list
const items = ['First', 'Second', 'Third'];
const numbered = items.map((item, index) => `${index + 1}. ${item}`);
console.log(numbered); // ['1. First', '2. Second', '3. Third']
Chaining map() with Other Methods
map() and filter()
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Double even numbers only
const doubledEvens = numbers
.filter((num) => num % 2 === 0)
.map((num) => num * 2);
console.log(doubledEvens); // [4, 8, 12, 16, 20]
// Map then filter
const processed = numbers
.map((num) => num ** 2)
.filter((squared) => squared > 25);
console.log(processed); // [36, 49, 64, 81, 100]
// Complex chaining
const users = [
{ name: 'John', age: 30, active: true },
{ name: 'Jane', age: 25, active: false },
{ name: 'Bob', age: 35, active: true },
];
const activeUserNames = users
.filter((user) => user.active)
.map((user) => user.name)
.map((name) => name.toUpperCase());
console.log(activeUserNames); // ['JOHN', 'BOB']
map() and reduce()
const orders = [
{ id: 1, items: [{ price: 10 }, { price: 20 }] },
{ id: 2, items: [{ price: 15 }, { price: 25 }] },
{ id: 3, items: [{ price: 30 }] },
];
// Calculate total for each order, then sum all
const totalRevenue = orders
.map((order) => order.items.reduce((sum, item) => sum + item.price, 0))
.reduce((total, orderTotal) => total + orderTotal, 0);
console.log(totalRevenue); // 100
// Transform and aggregate
const items = [
{ name: 'Apple', quantity: 5, price: 0.5 },
{ name: 'Banana', quantity: 3, price: 0.3 },
{ name: 'Orange', quantity: 2, price: 0.8 },
];
const invoice = items
.map((item) => ({
...item,
total: item.quantity * item.price,
}))
.reduce(
(acc, item) => ({
items: [...acc.items, item],
grandTotal: acc.grandTotal + item.total,
}),
{ items: [], grandTotal: 0 }
);
Real-World Use Cases
Data Formatting
// Format API response
const apiResponse = [
{ user_id: 1, first_name: 'John', last_name: 'Doe' },
{ user_id: 2, first_name: 'Jane', last_name: 'Smith' },
];
const formatted = apiResponse.map((user) => ({
id: user.user_id,
name: `${user.first_name} ${user.last_name}`,
initials: `${user.first_name[0]}${user.last_name[0]}`,
}));
// Format dates
const events = [
{ name: 'Meeting', date: '2025-01-15' },
{ name: 'Conference', date: '2025-02-20' },
];
const formattedEvents = events.map((event) => ({
...event,
formattedDate: new Date(event.date).toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
}),
}));
React Component Rendering
// Rendering list items
const TodoList = ({ todos }) => (
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<span>{todo.text}</span>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
);
// Creating options for select
const CountrySelect = ({ countries }) => (
<select>
{countries.map((country) => (
<option key={country.code} value={country.code}>
{country.name}
</option>
))}
</select>
);
// Dynamic component creation
const features = [
{ icon: '🚀', title: 'Fast', description: 'Lightning quick' },
{ icon: '🛡️', title: 'Secure', description: 'Bank-level security' },
{ icon: '📱', title: 'Mobile', description: 'Works everywhere' },
];
const FeatureCards = () => (
<div className="features">
{features.map((feature, index) => (
<div key={index} className="feature-card">
<span className="icon">{feature.icon}</span>
<h3>{feature.title}</h3>
<p>{feature.description}</p>
</div>
))}
</div>
);
Data Validation and Sanitization
// Validate and clean user input
const userInputs = [
' john@example.com ',
'JANE@EXAMPLE.COM',
'invalid-email',
'bob@example.com',
];
const validEmails = userInputs
.map((email) => email.trim().toLowerCase())
.filter((email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email));
// Sanitize form data
const formData = [
{ field: 'name', value: ' John Doe ' },
{ field: 'email', value: 'JOHN@EXAMPLE.COM' },
{ field: 'phone', value: '123-456-7890' },
];
const sanitized = formData.map(({ field, value }) => ({
field,
value: field === 'email' ? value.toLowerCase().trim() : value.trim(),
}));
map() vs Other Methods
map() vs forEach()
const numbers = [1, 2, 3, 4, 5];
// map() - returns new array
const doubled1 = numbers.map((n) => n * 2);
console.log(doubled1); // [2, 4, 6, 8, 10]
// forEach() - returns undefined
const doubled2 = numbers.forEach((n) => n * 2);
console.log(doubled2); // undefined
// When to use forEach
const results = [];
numbers.forEach((n) => {
// Side effects
console.log(n);
results.push(n * 2);
});
// When to use map
const transformed = numbers.map((n) => n * 2); // Pure transformation
map() vs filter()
// map() - transforms all elements (same length)
const allSquared = [1, 2, 3, 4].map((n) => n ** 2);
console.log(allSquared); // [1, 4, 9, 16]
// filter() - selects elements (different length)
const evens = [1, 2, 3, 4].filter((n) => n % 2 === 0);
console.log(evens); // [2, 4]
// Combining both
const evenSquares = [1, 2, 3, 4].filter((n) => n % 2 === 0).map((n) => n ** 2);
console.log(evenSquares); // [4, 16]
map() vs reduce()
// map() - one-to-one transformation
const prices = [10, 20, 30];
const withTax = prices.map((price) => price * 1.2);
console.log(withTax); // [12, 24, 36]
// reduce() - many-to-one transformation
const total = prices.reduce((sum, price) => sum + price, 0);
console.log(total); // 60
// Sometimes reduce can replace map
const doubled = prices.reduce((acc, price) => {
acc.push(price * 2);
return acc;
}, []); // [20, 40, 60] - but map() is clearer
Advanced Techniques
Async Operations with map()
// map() with promises
const urls = ['/api/user/1', '/api/user/2', '/api/user/3'];
// This returns array of promises
const promises = urls.map((url) => fetch(url).then((r) => r.json()));
// Wait for all
const users = await Promise.all(promises);
// Async function in map
const processedUsers = await Promise.all(
users.map(async (user) => {
const details = await fetchUserDetails(user.id);
return { ...user, ...details };
})
);
// Sequential async processing
async function processSequentially(items) {
const results = [];
for (const item of items) {
const result = await processItem(item);
results.push(result);
}
return results;
}
Conditional Mapping
// Map with conditions
const numbers = [1, 2, 3, 4, 5];
const conditional = numbers.map((n) => (n % 2 === 0 ? n * 2 : n * 3));
console.log(conditional); // [3, 4, 9, 8, 15]
// Complex conditions
const users = [
{ name: 'John', age: 30, type: 'admin' },
{ name: 'Jane', age: 25, type: 'user' },
{ name: 'Bob', age: 35, type: 'guest' },
];
const processed = users.map((user) => {
switch (user.type) {
case 'admin':
return { ...user, permissions: ['read', 'write', 'delete'] };
case 'user':
return { ...user, permissions: ['read', 'write'] };
default:
return { ...user, permissions: ['read'] };
}
});
Nested Mapping
// Map over nested arrays
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const doubled = matrix.map((row) => row.map((num) => num * 2));
console.log(doubled); // [[2,4,6], [8,10,12], [14,16,18]]
// Flatten while mapping
const flattened = matrix.map((row) => row.map((num) => num * 2)).flat();
// Or use flatMap
const flattened2 = matrix.flatMap((row) => row.map((num) => num * 2));
// Deep object mapping
const data = {
users: [
{ name: 'John', scores: [80, 90, 85] },
{ name: 'Jane', scores: [95, 88, 92] },
],
};
const averages = data.users.map((user) => ({
name: user.name,
average: user.scores.reduce((a, b) => a + b, 0) / user.scores.length,
}));
Common Pitfalls and Solutions
Not Returning a Value
// Pitfall - forgetting to return
const numbers = [1, 2, 3];
const result = numbers.map((n) => {
n * 2; // Missing return!
});
console.log(result); // [undefined, undefined, undefined]
// Solution
const result2 = numbers.map((n) => {
return n * 2;
});
// Or use implicit return
const result3 = numbers.map((n) => n * 2);
Modifying Original Array
// Pitfall - mutating objects
const users = [{ name: 'John', age: 30 }];
const updated = users.map((user) => {
user.age = 31; // Modifies original!
return user;
});
console.log(users[0].age); // 31 - original changed!
// Solution - create new objects
const updated2 = users.map((user) => ({
...user,
age: 31,
}));
Using map() for Side Effects
// Pitfall - using map for side effects only
const numbers = [1, 2, 3];
numbers.map((n) => console.log(n)); // Don't do this!
// Solution - use forEach for side effects
numbers.forEach((n) => console.log(n));
// Or use map when you need the result
const logged = numbers.map((n) => {
console.log(n);
return n * 2;
});
Performance Considerations
// Avoid multiple passes
const numbers = [1, 2, 3, 4, 5];
// Less efficient - two passes
const result1 = numbers.map((n) => n * 2).map((n) => n + 1);
// More efficient - one pass
const result2 = numbers.map((n) => n * 2 + 1);
// For large datasets, consider alternatives
// Traditional for loop can be faster
const hugeArray = Array(1000000).fill(1);
// map()
console.time('map');
const mapped = hugeArray.map((n) => n * 2);
console.timeEnd('map');
// for loop
console.time('for');
const result = new Array(hugeArray.length);
for (let i = 0; i < hugeArray.length; i++) {
result[i] = hugeArray[i] * 2;
}
console.timeEnd('for');
Best Practices
- Always return a value from the callback function
- Don't modify the original array or its elements
- Use map() for transformations, not side effects
- Chain wisely - consider performance implications
- Create new objects/arrays when mapping objects
- Consider alternatives for simple operations on large datasets
- Use meaningful variable names in callbacks
- Handle edge cases like empty arrays
Conclusion
The map()
method is essential for functional programming in JavaScript. Key points:
- Creates a new array by transforming each element
- Doesn't modify the original array
- Perfect for data transformation and rendering lists
- Can be chained with other array methods
- Always returns an array of the same length
Master map()
to write cleaner, more functional JavaScript code. It's one of the most versatile tools in your array manipulation toolkit!