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.

6 min read

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.

javascriptjavascript
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:

javascriptjavascript
array.filter(callback)
ParameterDescription
elementThe current element
indexThe index of the current element
arrayThe 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:

javascriptjavascript
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.

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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:

javascriptjavascript
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

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.
RunePowered by Rune AI

Frequently Asked Questions

Does filter() change the original array?

No. filter() always returns a new array and leaves the original untouched. It is a non-mutating method.

What happens if no elements pass the test?

filter() returns an empty array []. It never returns null or undefined.

Can I use filter() with Boolean to remove falsy values?

Yes. arr.filter(Boolean) removes all falsy values (null, undefined, 0, '', false, NaN) from the array. This is a common shorthand for cleaning up sparse arrays.

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.