JavaScript Array Methods: Complete Guide 2026
Why Array Methods Define Modern JavaScript
JavaScript array methods are the foundation of functional programming patterns in modern JavaScript and TypeScript. Mastering map, filter, reduce, and their companions eliminates most for loops from your code, produces more readable and composable logic, and integrates naturally with React's state management patterns, data transformation pipelines, and API response processing. The array methods introduced in ES2019-2024 (flat, flatMap, at, findLast, toSorted, toSpliced, with) have further expanded what's possible without mutation or complex loops.
map: Transform Every Element
Array.map() creates a new array by applying a transformation function to every element. It's the most-used array method in React development — transforming API response arrays into JSX elements, transforming data shapes for display, and creating derived arrays from state. map always returns an array of the same length as the input. If the transformation can return null or undefined for some elements, combine map with filter to remove falsy values, or use flatMap which can remove elements by returning an empty array.
filter: Select Elements by Condition
Array.filter() creates a new array containing only elements for which the callback returns true. Combine filter with map to transform a subset of elements. The order matters for performance: filter first to reduce the array size, then map to transform the smaller array. filter is pure — it never mutates the original array, making it safe for React state patterns where mutation causes rendering bugs.
reduce: The Swiss Army Knife
Array.reduce() is the most powerful and most misused array method. It accumulates a single value from all array elements. Use it for: summing numbers, grouping records by a property (producing an object from an array), counting occurrences, flattening nested arrays (though flat() is more readable for this), and building lookup maps from arrays. The common mistake: using reduce when map or filter is clearer. Prefer readable alternatives when they exist — reach for reduce only when the output type differs from the input type.
Modern Array Methods (ES2023-2024)
toSorted(), toReversed(), and toSpliced() are the non-mutating versions of sort(), reverse(), and splice(). They return a new array instead of mutating in place — critical for React state and functional programming patterns. Array.at(-1) accesses the last element cleanly without arr[arr.length - 1]. findLast() and findLastIndex() search from the end. Array.from({length: n}, (_, i) => i) creates arrays of sequential values. Object.groupBy() (Stage 4, available in modern environments) groups array elements by a key function, replacing many complex reduce patterns with a single clean call. Download JavaScript utility templates and code snippets at proofmatcher.com.
Searching and Testing: find, some, every, includes
Not every task needs a new array. When you need a single item, find() returns the first element that matches a condition, and findIndex() returns its position; findLast() and findLastIndex() search from the end. When you only need a yes or no answer, some() returns true if at least one element matches and every() returns true if all of them do. Both stop as soon as the answer is known, which makes them faster than filtering and checking the length. For simple value checks, includes() is the clearest option and correctly handles NaN, unlike indexOf().
Grouping with Object.groupBy
Grouping items by a property used to require a reduce call that many developers found hard to read. ES2024 added Object.groupBy(items, callback), which returns an object whose keys are the values returned by the callback and whose values are arrays of matching items. For example, Object.groupBy(orders, (o) => o.status) produces { paid: [...], pending: [...] }. When keys are not strings, such as objects or dates, Map.groupBy returns a Map instead. Both are supported in all modern browsers and current Node.js versions.
Sorting Without Surprises
The default sort() converts elements to strings and compares them alphabetically, so [10, 2, 1].sort() returns [1, 10, 2]. Always pass a comparator for numbers, such as (a, b) => a - b, and use a.localeCompare(b) for text so accented characters and different languages sort correctly. Remember that sort() changes the original array. In React state and other code that must not mutate data, use toSorted(), which returns a sorted copy, alongside its siblings toReversed(), toSpliced(), and with().
Immutability and React State
React decides whether to re-render by comparing references, so updating state requires new arrays rather than changed ones. Use [...items, newItem] to add, items.filter((i) => i.id !== id) to remove, items.map((i) => i.id === id ? { ...i, done: true } : i) to update one item, and toSorted() to reorder. Methods such as push, splice, sort, and reverse mutate the existing array and lead to bugs where the screen does not update.
Readability and Performance
Chaining methods such as items.filter(...).map(...) is expressive and fast enough for the vast majority of arrays, including thousands of items. Optimise only when profiling shows a real problem. When it does, combining steps into a single pass with reduce or a plain for...of loop avoids creating intermediate arrays. A loop is also the right tool when you need to stop early with break, run await calls in sequence, or perform side effects, since forEach cannot be stopped and ignores returned promises. For converting other collections, Array.from() turns sets, maps, strings, and DOM lists into arrays and accepts a mapping function as its second argument.
TypeScript Tips for Array Methods
TypeScript understands array methods well. Since TypeScript 5.5, filtering out empty values with items.filter((x) => x !== undefined) correctly narrows the result type, so you no longer need a manual type guard in simple cases. When using reduce, provide the initial value's type explicitly, such as reduce<Record<string, number>>((acc, item) => ..., {}), because inference from an empty object or array is often too narrow. Enabling noUncheckedIndexedAccess also reminds you that array[0] and at() may return undefined, which prevents a common class of runtime errors.
A Quick Reference
- Transform:
map,flatMap - Select:
filter,find,findLast,slice - Check:
some,every,includes - Combine:
reduce,Object.groupBy,join - Reorder without mutation:
toSorted,toReversed,with
Practical Recipes
A few patterns come up in almost every project. To remove duplicate primitive values, create a set and spread it back into an array: [...new Set(tags)]. To remove duplicate objects by a key, build a map keyed by that property and take its values: [...new Map(users.map((u) => [u.id, u])).values()], which keeps the last occurrence of each ID. To calculate a total, use reduce with a numeric starting value: cart.reduce((sum, item) => sum + item.price * item.qty, 0). To flatten nested lists, flat() removes one level of nesting, and flatMap() maps and flattens in a single step, which is ideal when each item produces zero or more results.
To split an array into chunks, for example to send items to an API in batches of 50, use Array.from({ length: Math.ceil(items.length / 50) }, (_, i) => items.slice(i * 50, i * 50 + 50)). To create a lookup table from an array for fast access by ID, use Object.fromEntries(items.map((i) => [i.id, i])) or a Map. And to get the last element without calculating the length, use at(-1). Keeping these recipes in mind removes most of the situations where developers reach for a utility library.