Lodash isMatch Logic for Nested Arrays of Objects
This article explains the internal comparison algorithm executed by
Lodash's _.isMatch when evaluating deeply nested arrays of
objects. It details how Lodash propagates partial comparison flags,
performs existential subset searches rather than strict index matching
across arrays, handles recursive object matching, and prevents infinite
recursion using internal stack tracking.
The Comparison Bitmask and Flag Propagation
When _.isMatch(object, source) is invoked, Lodash
delegates the operation to internal functions—primarily
baseIsMatch and baseIsEqual. The evaluation
applies a bitwise flag known internally as
COMPARE_PARTIAL_FLAG (value 1).
This flag enforces partial matching throughout the traversal. Unlike
strict equality checks (such as _.isEqual), which require
identical structure, key counts, and array lengths, the partial flag
instructs Lodash to only verify that values defined in
source exist within object. This flag persists
recursively down through every level of nested objects and arrays.
Object-Level Comparison Logic
For each object encountered:
- Key Inspection: Lodash extracts all own enumerable
string-keyed properties from the
sourceobject usingkeys(source). - Existence Verification: It checks if each key in
sourceis present in thetargetobject. - Deep Value Delegation: If a key exists in both,
Lodash recursively evaluates the two values with
baseIsEqual, passing down theCOMPARE_PARTIAL_FLAG. If any key insourceis missing or fails the recursive match, the routine immediately short-circuits and returnsfalse.
Array-Level Comparison Logic (Existential Subset Matching)
When the algorithm encounters arrays inside nested objects, the behavior diverges significantly from standard equality:
- No Strict Index Binding: Lodash does not require
elements in the
sourcearray to appear at the exact same index in thetargetarray. - Subset Validation: The algorithm checks whether
every item in the
sourcearray matches at least one item in thetargetarray. The target array may contain additional elements not present in the source array without causing the comparison to fail. - Duplicate Prevention: When evaluating whether each
sourceitem has an equivalent in thetarget, Lodash tracks matched indices in the target array. An individual element in thetargetarray cannot be used to satisfy multiple distinct elements in thesourcearray unless duplicates exist in the target.
Evaluating Nested Arrays of Objects
When arrays contain nested objects, these two mechanisms operate in tandem recursively:
- Outer Array Step: Lodash iterates through the
elements of the
sourcearray. - Candidate Search: For each object in the
sourcearray, it scans thetargetarray to find a candidate object that satisfies a partial match. - Inner Object Step: The candidate object in the
targetarray is checked to see if it contains all properties of thesourceobject. If thesourceobject itself contains another nested array, the existential array-matching algorithm runs again for that nested layer. - Backtracking and Matching: If a target object partially matches the source object, that target item is flagged as consumed for this comparison branch. If it fails, the search moves to the next item in the target array.
- Resolution: If every object in the
sourcearray successfully finds a partially matching, unconsumed counterpart in thetargetarray, the array comparison resolves totrue. If anysourceitem finds no corresponding target object, it resolves tofalse.
Circular References and Short-Circuiting
To maintain performance and prevent call-stack overflows during deep
traversals, Lodash uses an internal Stack cache. As objects
and arrays are traversed, their references are stored in this stack. If
a circular reference is encountered, Lodash checks whether the pair is
already currently being evaluated, preventing infinite recursion.
Additionally, comparison functions evaluate primitives and mismatches
eagerly, short-circuiting to false at the earliest point of
divergence.