Overview
Know which methods mutate the array: mutation bypasses change detection in React and other frameworks. The ES2023 additions (toSorted, toReversed, toSpliced, with, findLast) have copying equivalents of every old mutating method; they need Node 20 or a current browser.
Copy: return a new array or value
Use these in React state and other change-detected code.
| Method | Returns | Notes |
|---|---|---|
map(fn), filter(fn) | New array | Transform / keep truthy results. map skips holes. |
flatMap(fn), flat(depth) | New array | One level by default; flat(Infinity) flattens fully. |
slice(start, end), concat(...) | New array | Shallow copy of a range / joined arrays. |
toSorted(cmp), toReversed() | New array | Non-mutating sort and reverse. |
toSpliced(i, del, ...items), with(i, v) | New array | Non-mutating splice and element replace. |
at(i) | Element | Negative index counts from the end: at(-1). |
join(sep) | String | Concatenate with a separator. |
Search and test
Use some, every, and includes for yes/no questions instead of find.
| Method | Returns | Notes |
|---|---|---|
find(fn), findLast(fn) | Element or undefined | First / last match. |
findIndex(fn), findLastIndex(fn) | Index or -1 | |
indexOf(v), includes(v) | Index or -1 / boolean | includes finds NaN; indexOf does not. |
some(fn), every(fn) | Boolean | Short-circuit. |
Iterate and reduce
Use for...of when you need break, continue, or await.
| Method | Returns | Notes |
|---|---|---|
forEach(fn) | undefined | Side effects only; cannot break or await. |
reduce(fn, init), reduceRight | Any | Always pass init. |
entries(), keys(), values() | Iterator | Use with for...of. |
Object.groupBy(arr, fn) | Object of arrays | Baseline since March 2024 (Node 21+); Map.groupBy for non-string keys. |
Array.from(iterable, mapFn), Array.of(...), Array.isArray(v) | Array / boolean | Conversion and checks. |
const byType = Object.groupBy(items, (i) => i.type) // { fruit: [...], meat: [...] }
const sum = [1, 2, 3].reduce((acc, x) => acc + x, 0) // 6
for (const [i, v] of arr.entries()) { /* break, continue, await all work here */ }Mutate in place
Copy first when the array is React state: setItems((prev) => [...prev, item]), prev.filter((x) => x.id !== id).
| Method | Returns |
|---|---|
push(...), unshift(...) | New length |
pop(), shift() | Removed element |
splice(i, del, ...items) | Removed elements |
sort(cmp), reverse(), fill(v, s, e), copyWithin(t, s) | The same array |
Gotchas
Avoid these; each returns a surprising value without an error.
| Gotcha | Fix |
|---|---|
sort() compares as strings: [10, 2, 1].sort() is [1, 10, 2]. | Pass a comparator: (a, b) => a - b. |
reduce on an empty array without init throws TypeError. | Pass 0, [], or {}. |
forEach ignores returned promises and cannot stop early. | Use for...of, or Promise.all(arr.map(...)). |
Array(3).map(fn) skips the empty slots. | Array.from({ length: 3 }, fn). |
splice mutates and returns the removed items, unlike slice. | Use toSpliced for a copy. |
typeof [] is "object". | Use Array.isArray. |