filter()
ES5+Creates a new array with all elements that pass the test implemented by the provided function.
Syntax
array.filter(callback(element, index, array), thisArg)Parameters
callback Function Function to test each element of the array
Return Value
A new array with elements that pass the test
Examples
const numbers = [1, 2, 3, 4, 5, 6];
const evens = numbers.filter(x => x % 2 === 0);
console.log(evens); 📌 When to Use
Use filter() when you need a new array containing only the elements that satisfy a condition, leaving the original untouched. It shines in search interfaces, permission checks over collections, removing invalid or expired entries, and any place where "keep the items where X is true" describes the goal. Choosing between the lookup methods matters: if you only need the first match, find() stops early and returns the element itself; if you only need a yes-or-no answer, some() or every() short-circuits without building an array; if you need the position of a match, use findIndex(). filter() is the right tool specifically when the output is another collection you will iterate, render, or process further. Because it never mutates, filter() is also the idiomatic way to "remove" items in state-driven frameworks: setTodos(todos.filter(t => t.id !== id)) produces the new state React or Svelte expects instead of splicing the old array. When you need to both select and reshape elements, either chain filter() into map() or collapse both steps into a single flatMap() or reduce() if the intermediate array would be wastefully large.
⚠️ Common Mistakes
Using filter()[0] to locate a single element. filter() always scans the entire array and allocates a result array even when the first element already matched; find() stops at the first hit and returns the element directly. On large lists the difference is both wasted time and wasted memory.
Relying on accidental truthiness in the predicate. filter() coerces whatever the callback returns to a boolean, so users.filter(u => u.name) quietly drops users whose name is an empty string, and nums.filter(n => n) removes legitimate zeros along with null and undefined. Write the condition you actually mean, such as n !== null.
Expecting filter() to modify the original array. It always returns a new array and leaves the source untouched, so arr.filter(...) as a bare statement does nothing visible - the filtered result is silently discarded. Assign the return value or pass it onward.
Passing an async predicate. An async function always returns a Promise, and every Promise is truthy, so arr.filter(async x => await check(x)) keeps every single element regardless of what check() resolves to. Resolve the checks first with Promise.all(), then filter on the resolved booleans.
Deduplicating with arr.filter((x, i) => arr.indexOf(x) === i). It works, but indexOf() rescans the array for every element, making the whole operation O(n^2) - noticeably slow past a few thousand items. [...new Set(arr)] does the same job in linear time for primitive values.
✅ Best Practices
Compose filter() with map() to express select-then-transform pipelines declaratively, and keep the filter step first so later stages touch only the surviving elements. If profiling shows the intermediate array matters, the same logic collapses cleanly into one flatMap() or reduce() pass.
Extract complex predicates into named functions such as isActiveAdult or isWithinBudget. products.filter(isInStock) reads like a sentence, the predicate becomes independently unit-testable, and the same function can be reused by find(), some(), and every() without duplicating the condition.
Use arr.filter(Boolean) as the idiomatic one-liner for stripping all falsy values (null, undefined, 0, "", NaN, false) from a mixed list - but only when dropping zeros and empty strings is genuinely what you want; otherwise write an explicit null check.
In TypeScript, use a type-guard predicate to narrow the result type: values.filter((v): v is string => typeof v === "string") produces string[] instead of (string | number)[], removing the need for casts downstream.
Combine multiple conditions in one predicate with && rather than chaining several filter() calls. One pass over the data is faster, allocates a single result array instead of several intermediates, and keeps all the selection logic visible in one place.
⚡ Performance Notes
filter() is O(n): it visits every element exactly once and cannot stop early, because it must find all matches. Unlike map(), the engine cannot pre-size the output - V8 grows the result array dynamically as matches accumulate, so a filter that keeps most elements performs a few internal reallocations along the way. That cost is trivial for typical UI lists but shows up when filtering millions of rows repeatedly, for example on every keystroke of a search box; there, debounce the input, filter a pre-narrowed candidate set, or index the data in a Map keyed by the search field. Chaining arr.filter(a).filter(b) allocates an intermediate array that a combined predicate (x => a(x) && b(x)) avoids. For membership-style filtering against another list, build a Set first: keep.has(x.id) inside the predicate turns an O(n*m) double loop into O(n+m).
🌍 Real World Example
Filtering Products by Search and Category
A product listing page almost always combines several independent criteria: the category the user picked, the text they typed, and stock availability. Expressing all three as one predicate keeps the logic in a single pass and a single place, so adding a price-range condition later is a one-line change. Note the case normalization with toLowerCase() on both sides of the comparison - forgetting it is the most common reason search "misses" obviously matching products. Because filter() never mutates, the full products array stays intact for when the user clears the search box.
const products = await fetchProducts();
const searchTerm = 'laptop';
const category = 'electronics';
const filtered = products.filter(product =>
product.category === category &&
product.name.toLowerCase().includes(searchTerm.toLowerCase()) &&
product.inStock
);
// Only shows in-stock laptops in electronics category