How Lodash _.pull Mutates Arrays in Place
This article examines how the _.pull method in the
Lodash JavaScript library operates directly on an array to remove
specified elements. It explains the mechanics of in-place mutation,
contrasts the method with non-destructive alternatives, outlines the
internal algorithm used to alter the array reference, and highlights the
performance and architectural implications of mutating data directly in
JavaScript applications.
What Does In-Place Mutation Mean?
In JavaScript, mutating an array "in place" means modifying the existing array stored in memory rather than allocating and returning a new array instance. When a method mutates an array in place, any variable holding a reference to that array will immediately reflect the changes.
The _.pull method follows this pattern. Its signature
is:
_.pull(array, [values])It takes the target array as its first argument, followed by the
values to remove. Instead of producing a filtered shallow copy,
_.pull directly modifies the passed-in array
and returns a reference to that exact same array.
const original = ['a', 'b', 'c', 'a', 'b', 'c'];
const result = _.pull(original, 'a', 'c');
console.log(original); // ['b', 'b']
console.log(result); // ['b', 'b']
console.log(original === result); // trueHow _.pull Works
Under the Hood
To achieve in-place removal, Lodash iterates through the target array
and checks each element against the provided set of values using the
SameValueZero equality algorithm (similar to
===, but treats NaN as equal to
NaN).
The internal process works as follows:
- Argument Extraction: Lodash gathers all arguments passed after the target array into an internal collection of values to be removed.
- Index Traversal: The algorithm scans the array. When an element matches one of the target values, its index is recorded.
- Element Shifting (Splicing): The matching element
is removed by shifting subsequent elements to the left to fill the gap,
directly decremented against the array's
lengthproperty (similar to nativeArray.prototype.splice). - Index Adjustment: Because elements shift left when an item is removed, the traversal index is adjusted to prevent skipping adjacent duplicates.
- Return Value: Lodash returns the original array
reference, which now has a reduced
lengthand contains only the un-pulled values.
Contrast With
_.without
Lodash provides a non-mutating alternative called
_.without. Understanding the difference highlights why
_.pull is distinct:
_.pull(array, ...values): Mutatesarraydirectly. Memory reference remains unchanged._.without(array, ...values): Leaves the originalarrayuntouched and creates a new array excluding the specified values, functioning similarly to nativeArray.prototype.filter().
const numbers = [1, 2, 3];
// Non-mutating
const filtered = _.without(numbers, 2);
console.log(numbers); // [1, 2, 3]
console.log(filtered); // [1, 3]
// Mutating
_.pull(numbers, 2);
console.log(numbers); // [1, 3]Considerations When Using
_.pull
Using _.pull can be beneficial for memory management in
performance-critical scenarios involving large arrays because it avoids
the overhead of allocating new array objects and triggering garbage
collection.
However, in-place mutation introduces side effects. In environments
that rely on immutability—such as React state management, Redux, or
functional programming paradigms—mutating an array in place will bypass
shallow reference equality checks, potentially preventing UI re-renders
or causing unpredictable bugs. In such contexts, _.without
or native .filter() should be used instead.