How Lodash _.filter Preserves Matching Elements
The _.filter method in the Lodash JavaScript library is
designed to iterate through a collection and extract elements that
satisfy a specific condition, returning them in a brand-new array. This
article breaks down the internal mechanism of _.filter,
explaining how it evaluates truthiness via predicate functions,
guarantees original order, maintains immutability, and shallow-copies
matching values directly into the result set.
Core Mechanism of
_.filter
Lodash's _.filter operates as a non-destructive
iteration utility. It traverses an array or object from start to finish,
evaluates each value against a designated predicate function, and stores
the values that pass the test into an internally created array.
The process follows a deterministic sequence:
- Initialization: Lodash instantiates an empty array
(
[]) to hold the matching results. - Iteration: The method sequentially loops through the elements of the target collection using standard zero-indexed iteration for arrays or key-enumeration for objects.
- Predicate Invocation: For each element, Lodash
calls the predicate callback, passing three arguments: the current
element (
value), the current index or key (index/key), and the entire source collection (collection). - Truthiness Check: The returned result of the
predicate is evaluated for truthiness. In JavaScript, any value other
than
false,0,"",null,undefined, andNaNis considered truthy. - Collection and Preservation: If the predicate returns a truthy value, Lodash pushes that exact element reference into the newly created array. If the predicate returns a falsy value, the element is skipped.
- Return: Once iteration is complete, the new array containing only the preserved elements is returned.
Immutability and Shallow Copying
A key characteristic of how _.filter preserves elements
is immutability. The original collection remains completely
untouched.
When an element passes the predicate test, Lodash preserves it via a shallow copy. For primitive values (such as numbers, strings, and booleans), the value is copied directly. For complex types (such as objects or nested arrays), Lodash preserves the direct memory reference to that object. This ensures optimal memory performance, though modifying a nested property on a filtered object will reflect in the original collection.
Order Preservation
Lodash guarantees the preservation of sequence. Because
_.filter evaluates elements in order from the first index
(0) to the final index (length - 1), the
matching elements are placed into the output array in the exact relative
order in which they appeared in the source collection.
Predicate Shorthands
Beyond custom callback functions, Lodash enhances matching preservation through built-in predicate shorthands:
- Matches Shorthand: Passing an object
(
_.filter(users, { active: true })) internally invokes_.matches, preserving elements that match the source object's key-value pairs. - Matches Property Shorthand: Passing a key-value
array (
_.filter(users, ['active', true])) invokes_.matchesProperty. - Property Shorthand: Passing a single string key
(
_.filter(users, 'active')) invokes_.property, preserving any element where that specific property evaluates to a truthy value.
Practical Example
const users = [
{ id: 1, name: 'Alice', active: true },
{ id: 2, name: 'Bob', active: false },
{ id: 3, name: 'Charlie', active: true }
];
// Preserves elements where 'active' is true
const activeUsers = _.filter(users, (user) => user.active);
// Result:
// [
// { id: 1, name: 'Alice', active: true },
// { id: 3, name: 'Charlie', active: true }
// ]In this execution, users[0] and users[2]
return truthy evaluations, prompting Lodash to append their references
to the result array in their original chronological order, leaving
users unchanged.