JavaScript Array Filter Method: Complete Guide
filter() creates a new array with only the elements that pass a test. Learn how to select, exclude, and refine array data with clear examples.
filter() creates a new array containing only the elements that pass a test you provide. The original array is not changed. It is the go-to method for selecting, excluding, and refining data in an array.
const numbers = [10, 25, 8, 42, 3, 17];
const bigNumbers = numbers.filter(n => n > 15);
console.log(bigNumbers); // [25, 42, 17]
console.log(numbers); // [10, 25, 8, 42, 3, 17] (unchanged)Each element is passed to the callback. If the callback returns true, the element is included in the new array. If false, it is excluded.
The order of surviving elements always matches their original order in the source array.
Syntax and Parameters
filter() takes a single callback function and calls it once for every element in the array:
array.filter(callback)| Parameter | Description |
|---|---|
element | The current element |
index | The index of the current element |
array | The array filter() was called on |
The callback can be a named function, an arrow function, or a reference to an existing function like Boolean. Every element that produces a truthy return value is included in the result. The original element is what gets kept, not the callback's true or false result itself.
Filtering Objects by Property
filter() is most powerful when working with arrays of objects, where the condition checks a property instead of the raw value:
const products = [
{ name: "Laptop", price: 999, inStock: true },
{ name: "Mouse", price: 29, inStock: false },
{ name: "Keyboard", price: 79, inStock: true },
{ name: "Monitor", price: 299, inStock: true }
];
const available = products.filter(product => product.inStock);Only the three in-stock products make it into the result, in the same order they appeared in the original array. The out-of-stock mouse is dropped entirely rather than replaced with a placeholder.
console.log(available.length); // 3
console.log(available.map(p => p.name)); // ["Laptop", "Keyboard", "Monitor"]You can combine multiple conditions with && to narrow the results further, keeping only products that pass every single check in the callback:
const affordableAndAvailable = products.filter(
product => product.inStock && product.price < 100
);
console.log(affordableAndAvailable);
// [{ name: "Keyboard", price: 79, inStock: true }]Chaining filter() with map()
filter() and map() are often chained together to select and then transform. Filtering to the completed tasks first, then mapping to their titles, keeps each step focused on one job:
const tasks = [
{ title: "Buy milk", completed: true },
{ title: "Walk dog", completed: false },
{ title: "Read book", completed: true },
{ title: "Call mom", completed: false }
];
const completedTitles = tasks
.filter(task => task.completed)
.map(task => task.title);The filter step drops the two incomplete tasks, then map extracts just the title from each of the two that remain:
console.log(completedTitles); // ["Buy milk", "Read book"]The order matters: filter first to reduce the number of elements, then map to transform. This is more efficient than mapping first and then filtering, since map() then only runs on the elements that survived the filter. Reversing the order would still work correctly, but it would waste time transforming values that get discarded a moment later.
The same pattern works for formatting numeric data, filtering out failing scores before turning the rest into display strings:
const scores = [45, 72, 88, 39, 95, 61];
const formattedPassing = scores
.filter(score => score >= 60)
.map(score => `${score}% (pass)`);
console.log(formattedPassing);
// ["72% (pass)", "88% (pass)", "95% (pass)", "61% (pass)"]Filtering first ensures map() only runs on elements that matter, avoiding wasted computation on values you are going to throw away anyway.
Quick Cleanup with filter(Boolean)
Passing Boolean as the callback removes all falsy values:
const messy = [0, "hello", "", null, "world", undefined, false, "!", NaN];
const clean = messy.filter(Boolean);
console.log(clean); // ["hello", "world", "!"]Boolean is a built-in function that returns true for truthy values and false for falsy ones. filter(Boolean) is the standard shorthand for cleaning arrays, and it works because filter() only needs a function reference, not necessarily an arrow function you write yourself.
Using the Index Parameter
You can use the index to filter by position:
const items = ["a", "b", "c", "d", "e"];
// Keep only even-indexed elements
const evenIndexed = items.filter((_, i) => i % 2 === 0);
console.log(evenIndexed); // ["a", "c", "e"]The underscore _ is a convention for unused parameters. Here we only need the index, not the element value, so naming the first parameter with an underscore signals to readers that it is intentionally ignored.
Removing Duplicates with filter() and indexOf()
Before Set became common, filter() was used to remove duplicates by comparing each element's first occurrence to its current position in the array, keeping only the elements where those two positions match:
const numbers = [1, 2, 2, 3, 3, 3, 4];
const unique = numbers.filter(
(n, i) => numbers.indexOf(n) === i
);
console.log(unique); // [1, 2, 3, 4]The idea: keep the element only if its first occurrence in the array is at the current index. For any repeated value, only the earliest position satisfies that check, so later duplicates get filtered out.
Modern code usually uses [...new Set(numbers)] instead, since it expresses the same intent more directly. For a full guide, see Removing Duplicates from Arrays in JavaScript.
Common Mistakes
Expecting filter() to mutate the original array:
const items = [1, 2, 3, 4, 5];
// Wrong: expects filter to remove elements in place
items.filter(n => n > 3);
console.log(items); // [1, 2, 3, 4, 5] (unchanged!)
// Right: capture the result
const filtered = items.filter(n => n > 3);
console.log(filtered); // [4, 5]Using filter() when you only need a boolean answer. Building a whole filtered array just to check its length wastes work when you only care whether a match exists:
const users = [{ name: "Alice" }, { name: "Bob" }];
// Overkill: creates an array just to check if it exists
const hasAlice = users.filter(u => u.name === "Alice").length > 0;
// Better: use some() for boolean checks
const hasAliceBetter = users.some(u => u.name === "Alice");Use some() or every() when you only need to know whether elements exist, not which elements.
Accidentally modifying objects in the filtered array:
const users = [{ name: "Alice" }, { name: "Bob" }];
const filtered = users.filter(u => {
u.name = u.name.toUpperCase(); // Mutates the original object!
return u.name.startsWith("A");
});
console.log(users[0].name); // "ALICE" (original was mutated!)filter() does not copy objects. It includes a reference to the original object, so mutating an element inside the callback mutates the source array too, even though filter() itself never mutates the array structure.
Avoid side effects inside the callback. If you need to transform while filtering, chain map() after filter().
Now that you can select elements, learn how to combine all elements into a single value with reduce.
Rune AI
Key Insights
- filter() returns a new array containing only the elements that pass a truthiness test.
- The callback receives element, index, and the array itself, just like map() and forEach().
- filter(Boolean) is a quick way to remove all falsy values from an array.
- filter() is chainable with map(), reduce(), and other array methods.
- When no elements pass, filter() returns an empty array, never null or undefined.
Frequently Asked Questions
Does filter() change the original array?
What happens if no elements pass the test?
Can I use filter() with Boolean to remove falsy values?
Conclusion
filter() is the method you reach for whenever you need to select a subset of array elements. It is simple, non-mutating, and chainable. Combined with map(), it forms the backbone of functional array processing in JavaScript. For testing elements without selecting them, use some() and every() instead.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.