JavaScript arrays look simple until you need to choose the right method quickly: should you use map() or forEach(), find() or filter(), splice() or slice()? This cheat sheet is a practical reference for common and newer array methods, organized by use case so you can compare behavior, check syntax, and decide when each method fits best. Keep it nearby for day-to-day coding, interview prep, and code reviews.
Overview
This guide covers the array methods in JavaScript that developers reach for most often, plus a few that are easy to forget until you need them. Rather than listing methods alphabetically, it groups them by what you are trying to do: transform data, search, test conditions, add or remove items, copy or flatten arrays, sort results, or aggregate values.
The most useful comparison to keep in mind is this: some array methods return a new array, some return a single value, some return a boolean, and some mutate the original array. That distinction matters more than memorizing every signature.
Here is the quick mental model:
- Transform each item:
map() - Keep matching items:
filter() - Collapse to one result:
reduce() - Run side effects only:
forEach() - Find one matching item:
find() - Check whether any or all items match:
some(),every() - Add or remove items with mutation:
push(),pop(),shift(),unshift(),splice() - Copy without mutation:
slice(),concat(), spread syntax,toSorted(),toReversed(),toSpliced() - Sort or reverse:
sort(),reverse(), or the non-mutating newer versions - Flatten nested arrays:
flat(),flatMap()
If you work in teams, another useful rule is to prefer methods that communicate intent clearly. A short filter() or find() is often easier to review than a manual loop with temporary variables.
How to compare options
When choosing between array methods in JavaScript, compare them using five questions. This will help you avoid subtle bugs and write code that is easier to maintain.
1. Does it mutate the original array?
Mutation changes the existing array in place. That may be fine in small scripts, but it can create confusing state bugs in UI code, reducers, or shared utility functions.
- Mutating methods:
push(),pop(),shift(),unshift(),splice(),sort(),reverse(),fill(),copyWithin() - Non-mutating methods:
map(),filter(),reduce(),slice(),concat(),find(),some(),every(),flat() - Newer non-mutating alternatives:
toSorted(),toReversed(),toSpliced(),with()
If you need immutable updates, the newer copy-returning methods are worth revisiting as browser and runtime support evolves.
2. What does it return?
Many mistakes come from assuming one method returns the same shape as another.
map()returns a new array of equal lengthfilter()returns a new array, possibly shorterfind()returns one item orundefinedsome()andevery()return booleansreduce()returns whatever accumulator you buildforEach()returnsundefined
If you need a value to chain into the next step, forEach() is usually the wrong choice.
3. Do you need one result, many results, or just a check?
This is where methods often overlap:
- Use
find()for the first match - Use
filter()for all matches - Use
some()to ask “is there at least one?” - Use
every()to ask “do all items pass?”
4. Is readability better than cleverness here?
reduce() can solve many problems, but it should not replace clearer tools. If you are only transforming items, use map(). If you are only filtering, use filter(). Save reduce() for real accumulation logic.
5. Are sparse arrays or edge cases relevant?
Some methods skip empty slots, and some behave differently with missing values. In production code, arrays are often messy. If your input may contain holes, undefined, nested arrays, or mixed types, choose methods deliberately and test the edge cases.
Feature-by-feature breakdown
This section is the working reference. Each method includes syntax, what it returns, whether it mutates, and when to use it.
Transforming arrays
map() — create a new array by transforming every item.
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);
// [2, 4, 6]- Returns: new array
- Mutates: no
- Use when: output length stays the same and each item becomes something else
flatMap() — map each item, then flatten one level.
const words = ['hi there', 'ok'];
const parts = words.flatMap(s => s.split(' '));
// ['hi', 'there', 'ok']- Returns: new flattened array
- Mutates: no
- Use when: each item can produce zero, one, or many output items
forEach() — run a function for each item.
const nums = [1, 2, 3];
nums.forEach(n => console.log(n));- Returns:
undefined - Mutates: the method itself does not, but your callback can
- Use when: logging, DOM updates, counters, or side effects
- Avoid when: you need a returned array or chainable result
Filtering and searching
filter() — keep all items that pass a test.
const nums = [1, 2, 3, 4];
const evens = nums.filter(n => n % 2 === 0);
// [2, 4]- Returns: new array
- Mutates: no
- Use when: you want many matches
find() — return the first item that matches.
const users = [{id: 1}, {id: 2}];
const user = users.find(u => u.id === 2);
// { id: 2 }- Returns: item or
undefined - Mutates: no
- Use when: only one match matters
findIndex() and findLast()/findLastIndex() help when position matters or when you need the last match rather than the first.
includes() — check whether an array contains a value.
['js', 'ts'].includes('js');
// true- Returns: boolean
- Use when: exact value membership is enough
indexOf() is older and still useful, but includes() usually reads better if you only need a yes-or-no answer.
Testing conditions
some() — does at least one item pass?
const hasAdmin = users.some(u => u.role === 'admin');every() — do all items pass?
const allActive = users.every(u => u.active);- Returns: boolean
- Mutates: no
- Use when: your result is a condition, not a transformed array
Reducing to one value
reduce() — build a single result from the array.
const nums = [1, 2, 3, 4];
const sum = nums.reduce((total, n) => total + n, 0);
// 10It can also build objects, group values, or flatten custom structures.
const grouped = ['a', 'ab', 'b'].reduce((acc, item) => {
const key = item[0];
acc[key] ??= [];
acc[key].push(item);
return acc;
}, {});
// { a: ['a', 'ab'], b: ['b'] }- Returns: accumulator result
- Mutates: not the array itself
- Use when: you need one final value or a custom structure
- Tip: provide an initial value to avoid edge-case surprises
Adding and removing items
push() / pop() work at the end of the array.
const arr = [1, 2];
arr.push(3); // arr is [1, 2, 3]
arr.pop(); // returns 3shift() / unshift() work at the start.
const arr = [2, 3];
arr.unshift(1); // [1, 2, 3]
arr.shift(); // returns 1splice() inserts, removes, or replaces items in place.
const arr = ['a', 'b', 'c'];
arr.splice(1, 1, 'x');
// arr is ['a', 'x', 'c']- Returns: removed items
- Mutates: yes
- Use when: in-place edits are acceptable
toSpliced() is the copy-returning alternative when you want the same operation without mutation.
Copying and slicing
slice() returns a shallow copy of part of an array.
const arr = [1, 2, 3, 4];
const part = arr.slice(1, 3);
// [2, 3]- Mutates: no
- Use when: you need a subsection or shallow copy
concat() joins arrays without mutation.
const result = [1, 2].concat([3, 4]);
// [1, 2, 3, 4]Sorting and reversing
sort() sorts in place. That is important enough to repeat: it mutates.
const nums = [10, 2, 5];
nums.sort((a, b) => a - b);
// [2, 5, 10]Without a compare function, the result may be based on string ordering, which is often not what you want for numbers.
toSorted() returns a sorted copy instead.
reverse() mutates; toReversed() returns a reversed copy.
Flattening and filling
flat() removes nesting up to a given depth.
const arr = [1, [2, [3]]];
arr.flat(2);
// [1, 2, 3]fill() replaces a range with a static value.
const arr = new Array(3).fill(0);
// [0, 0, 0]- Mutates: yes
- Use when: initializing simple arrays
Joining and converting
join() turns an array into a string.
['a', 'b', 'c'].join('-');
// 'a-b-c'Array.from() is not an instance method, but it belongs in any JavaScript arrays reference because it converts iterable or array-like values into real arrays.
Array.from('abc');
// ['a', 'b', 'c']Best fit by scenario
If you do not remember exact syntax under pressure, this section is the shortcut. Start with the result you want, then choose the method that matches it.
I need to transform every item
Use map().
const labels = products.map(p => p.name);Use flatMap() if one item can turn into multiple results.
I need to remove items that do not match
Use filter().
const openIssues = issues.filter(issue => !issue.closed);I need one matching item
Use find().
const currentUser = users.find(u => u.id === sessionUserId);If you only need the position, use findIndex().
I need to know whether a condition is true
Use some() for “at least one,” and every() for “all.”
const hasErrors = logs.some(log => log.level === 'error');
const allValid = fields.every(field => field.valid);I need one final value, like a total or grouped object
Use reduce(), but only when simpler methods do not express the intent more clearly.
const total = cart.reduce((sum, item) => sum + item.price, 0);I need to update an array without mutating it
Use slice(), concat(), spread syntax, or newer copy-returning methods like toSpliced() and toSorted().
const updated = items.toSpliced(index, 1, replacement);If those newer methods are not available in your target runtime, you can still use older immutable patterns.
I need side effects only
Use forEach(). Typical examples: logging, analytics calls, DOM updates, or mutating an external object on purpose.
I need a quick interview answer
map(): transform every itemfilter(): keep matching itemsreduce(): combine into one valuefind(): first matchsome()/every(): boolean checksslice()vssplice(): copy vs mutate
A good interview explanation often includes both behavior and mutation: “I would use slice() because it returns a copy, while splice() changes the original array.”
When to revisit
This cheat sheet is worth revisiting whenever JavaScript adds new array helpers, when your runtime support changes, or when your team adopts stricter patterns around immutability and readability. The big update trigger is usually not syntax; it is the arrival of safer or clearer alternatives.
Here are the practical moments to come back and compare options again:
- When newer methods become available in your environment: methods like
toSorted(),toReversed(),toSpliced(), andwith()can simplify immutable updates - When code reviews keep flagging mutation issues: re-check where you are using
sort(),splice(), orreverse() - When performance work starts: compare chained operations against a single-pass approach only after identifying a real bottleneck
- When onboarding new developers: align on preferred patterns so the codebase is consistent
- When preparing for interviews: refresh the common comparisons people ask about, especially
map()vsforEach(),find()vsfilter(), andslice()vssplice()
To make this article useful in your own workflow, save a short checklist:
- Decide whether mutation is acceptable.
- Choose the method by return type: array, value, boolean, or side effect.
- Prefer the most specific method over a clever general one.
- Add an initial accumulator value for
reduce(). - Use newer non-mutating methods when your target runtime supports them.
If you want one final rule of thumb, use the method that tells the next reader what you meant. In most production code, that is the best array method choice you can make.
For more developer reference content and practical workflows, you may also like Language-Agnostic Semantic Graphs: Bringing MU to Your Multi-Language Codebase and Mining Fix Patterns: A Practical Workflow to Create Custom Static Analysis Rules.