Arrays — map, filter, reduce and the Rest
BeginnerThe array methods are how JavaScript expresses data transformation. Knowing which ones mutate and which return a new array is more important than knowing all of them.
Overview
Almost every screen in a real application is an array transformed into markup, so these methods are the ones you will type most. The split that matters is mutation: sort, reverse, splice, push and pop change the array in place, while map, filter, slice and concat return a new one. Mutating an array you did not create causes bugs that are hard to trace, and in React it causes renders to silently not happen — because a mutated array is still the same reference, so nothing looks changed.
The Three You Will Use Constantly
map transforms each item, filter selects a subset, reduce collapses to a single value. Everything else is a convenience on top of these.
const orders = [
{ id: 1, total: 4500, status: 'paid' },
{ id: 2, total: 1200, status: 'pending' },
{ id: 3, total: 8900, status: 'paid' },
]
// map — same length, transformed items
orders.map(o => o.total) // [4500, 1200, 8900]
// filter — fewer items, unchanged
orders.filter(o => o.status === 'paid') // 2 orders
// reduce — one value out
orders.reduce((sum, o) => sum + o.total, 0) // 14600
// Chaining is the normal shape:
const paidTotal = orders
.filter(o => o.status === 'paid')
.reduce((sum, o) => sum + o.total, 0) // 13400Mutating vs Non-Mutating
This is the distinction worth memorising. The mutating methods return something other than a new array, which is a useful tell.
// MUTATES the original:
arr.push(x) arr.pop() arr.shift() arr.unshift(x)
arr.splice(...) arr.sort(...) arr.reverse() arr.fill(...)
// RETURNS A NEW ARRAY:
arr.map(...) arr.filter(...) arr.slice(...) arr.concat(...)
arr.flat() arr.flatMap(...)
// The classic bug — sort mutates, and sorts as strings by default:
const prices = [100, 25, 9]
prices.sort() // [100, 25, 9] -> ['100','25','9'] -> [100, 25, 9]... wrong
prices.sort((a, b) => a - b) // [9, 25, 100] — correct, but prices is now changed
// Safe: copy first
const sorted = [...prices].sort((a, b) => a - b)
// or the newer non-mutating versions:
const sorted2 = prices.toSorted((a, b) => a - b)Searching and Checking
The rest of the API, grouped by what you are asking.
const users = [{ id: 1, name: 'Asha' }, { id: 2, name: 'Ravi' }]
users.find(u => u.id === 2) // the object, or undefined
users.findIndex(u => u.id === 2) // 1, or -1
users.some(u => u.name === 'Ravi') // true — at least one
users.every(u => u.id > 0) // true — all of them
users.includes(x) // strict equality, so no good for objects
// Grouping — reduce, or the newer Object.groupBy
const byStatus = orders.reduce((acc, o) => {
(acc[o.status] ??= []).push(o)
return acc
}, {})
// Flattening nested arrays
[[1, 2], [3, [4]]].flat() // [1, 2, 3, [4]]
[[1, 2], [3, [4]]].flat(2) // [1, 2, 3, 4]Key Points to Remember
- 1map transforms, filter selects, reduce collapses — most other methods are conveniences on these
- 2sort, reverse, splice, push and pop mutate in place; map, filter, slice and concat return new arrays
- 3sort() with no comparator sorts as strings, so [100, 25, 9] does not sort numerically
- 4Copy before sorting ([...arr].sort()) or use toSorted() — mutating shared arrays breaks React renders
- 5find returns the item, findIndex the position, some/every return booleans
Interview Questions
Sign in to ask AriaWhat is the difference between map and forEach?
Which common array methods mutate the original array?
Implement groupBy using reduce.
Ask Aria about Arrays — map, filter, reduce and the Rest
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.