Array.prototype.filter()

Returns a new array holding only the elements for which the callback returns a truthy value.

Signature
filter(callbackFn)
filter(callbackFn, thisArg)
  • Added in JavaScript ES5 (2009)

Parameters

ParameterTypeDescription
$callbackFnFunctionFunction run for each element. Called with (element, index, array); return a truthy value to keep the element and a falsy value to discard it.
$thisArgoptionalany= undefinedValue to use as this when executing callbackFn. Ignored by arrow functions.

Return value

ArrayA shallow copy of the array containing only the elements for which callbackFn returned a truthy value; an empty array if none did.

Errors

Nothing of its own — errors thrown by callbackFn propagate and stop the iteration.

filter() answers "which of these match?" It visits every element, keeps the ones whose callback result is truthy, and returns them in a brand-new array. The original is untouched, and the copy is shallow — object elements are the same references, not clones.

When to reach for it

  • Narrowing a list before rendering it.
  • Stripping empty, null or invalid entries out of parsed input.
  • Splitting a collection into two groups by running it twice with opposite conditions.

What trips people up

The callback must return the test. An arrow with braces and no return yields undefined — falsy — so you get an empty array back and no error to explain it.

filter() always walks the entire array. If you only want the first hit, find() stops early and hands you the element instead of a one-item array; the filter(...)[0] idiom is both slower and clumsier.

Truthiness, not equality, decides. filter(Boolean) removes 0, "", NaN, null, undefined and false — which is a neat trick for cleaning strings but silently drops legitimate zeros from numeric data. Test explicitly when zero is meaningful.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Show only orders above a threshold that are still unpaid
  • Drop null and empty-string entries from parsed CSV input
  • Deduplicate an array using indexOf on the third callback argument
  • Split a task list into completed and outstanding groups

Frequently asked questions

What is the difference between filter() and find()?

filter() returns an array of every match, find() returns the first matching element itself and stops searching there. If you expect at most one hit, find() is faster and saves you from unwrapping [0].

Why does my filter() return an empty array?

Almost always because the callback does not return anything. An arrow with a braced body like (x) => { x.age > 18 } returns undefined, which is falsy, so nothing passes. Drop the braces or add an explicit return.

Does filter() modify the original array?

No — it builds a new array and leaves the receiver unchanged. The new array holds the same object references, so mutating a filtered object still changes the object in the original array.

More examples

Cleaning falsy values out of parsed input

filter(Boolean) prints ['hi', 7, 'ok'] — it removed 0 and NaN along with the nullish values. The loose != null check prints [0, 'hi', '', 7, NaN, 'ok'], keeping the zero and the empty string, which is usually what you want for numeric data.

Example · javascript
const raw = [0, "hi", "", null, 7, undefined, NaN, "ok"];

console.log(raw.filter(Boolean));
console.log(raw.filter((x) => x != null));

Deduplicating with the index argument

Both print ['js', 'css', 'html']. The filter version keeps an element only when its first occurrence is at the current index. It is O(n²), so on large arrays the Set version on the last line is the better choice.

Example · javascript
const tags = ["js", "css", "js", "html", "css"];

const unique = tags.filter((tag, i, arr) => arr.indexOf(tag) === i);

console.log(unique);
console.log([...new Set(tags)]);

Discussion

  • Be the first to comment on this lesson.