Deep Nested Query Mapping in Lodash matchesProperty
This article explores the internal architecture of Lodash's
_.matchesProperty shorthand logic. It examines how Lodash
converts array-based path-value declarations into functional predicates,
normalizes nested property paths, navigates intermediate object
structures using recursive getters, and performs deep equality checks on
target values.
The Shorthand Dispatch Mechanism
When collection methods such as _.filter,
_.find, or _.some receive an array argument in
the form of [path, srcValue], Lodash intercepts this input
through its internal baseIteratee function. Rather than
treating the array as a standard callback, baseIteratee
inspects the structure of the input:
function baseIteratee(value) {
if (typeof value === 'function') {
return value;
}
if (value == null) {
return identity;
}
if (typeof value === 'object') {
return isArray(value)
? baseMatchesProperty(value[0], value[1])
: baseMatches(value);
}
return property(value);
}Recognizing a two-element array, the compiler delegates logic
directly to baseMatchesProperty(path, srcValue), creating a
reusable predicate function tailored for high-throughput evaluation.
Path
Normalization via castPath and
stringToPath
To support both dot-notation strings (e.g., 'a.b[0].c')
and pre-segmented key arrays (e.g., ['a', 'b', 0, 'c']),
Lodash normalizes the input query path.
castPath(path, object): Checks if the path is already an array or a simple single key on the object. If not, it invokesstringToPath.stringToPath(string): Uses an optimized regular expression to decompose property names, bracketed array indices, and escaped characters into a flat array of string keys. The internal cache (memoizeCapped) retains parsed paths to avoid redundant string parsing operations on recurring queries.
Intermediate Traversal via
baseGet
Once the path is decomposed into a flat sequence of string keys, the
predicate resolves the deeply nested target value using
baseGet.
baseGet iterates sequentially through the resolved path
tokens against the supplied object:
function baseGet(object, path) {
path = castPath(path, object);
var index = 0,
length = path.length;
while (object != null && index < length) {
object = object[toKey(path[index++])];
}
return (index && index == length) ? object : undefined;
}If any intermediate key resolves to null or
undefined, the traversal terminates early, preventing
TypeError: Cannot read properties of undefined exceptions
without requiring manual null guards.
Deep Comparison via
baseIsEqual
After retrieving the nested value at the resolved path,
baseMatchesProperty compares it to srcValue.
If srcValue is a primitive, the engine uses a fast strict
equality check via hasIn and === (with special
handling for NaN).
For complex objects or arrays, Lodash invokes
baseIsEqual configured with partial comparison flags:
COMPARE_PARTIAL_FLAG(1): Enforces that the target object contains at least the properties defined insrcValue, permitting the source object to contain unlisted keys.COMPARE_UNORDERED_FLAG(2): Handles un-ordered comparisons across structural mappings likeMaporSet.
Through the coordination of baseIteratee, path
decomposition via castPath, traversal via
baseGet, and assertion via baseIsEqual, Lodash
compiles the concise [path, srcValue] shorthand into an
optimized, null-safe deep query predicate.