Lodash isMatch: Partial Deep Comparison Explained
The Lodash _.isMatch method performs a partial deep
comparison between a target object and a source object to determine if
the target contains equivalent property values. Unlike a full deep
equality check, it only evaluates the properties present on the source
object, ignoring any extra keys on the target. This article details how
this deep partial comparison evaluates nested objects, handles arrays,
tests primitive values, and behaves in practical JavaScript
applications.
Understanding the Syntax and Core Concept
The method uses the following signature:
_.isMatch(object, source)object: The target object to inspect.source: The object specifying the property values to match.
The comparison is termed "partial" because the target
object is permitted to have additional properties that are
absent in source. As long as every property defined in
source exists in object with an equivalent
value, _.isMatch returns true.
What Makes the Comparison "Deep"?
A shallow comparison only evaluates top-level properties (similar to
checking object[key] === source[key]). In contrast,
_.isMatch recursively traverses nested data structures:
- Nested Objects: When a property value in
sourceis an object,_.isMatchdoes not compare references. Instead, it enters that nested object and recursively checks its keys against the corresponding nested object in the target. - Arrays: When traversing arrays,
_.isMatchtreats them as objects with numeric keys. It checks whether the target array contains equivalent values at the same indices defined in the source array. - Primitive Values: At the leaf nodes of the
traversal, values are compared using the
SameValueZeroalgorithm (similar to strict equality===, but treatingNaNas equal toNaN).
Practical Example
Consider the following scenario with deeply nested user data:
const user = {
id: 101,
name: "Alex",
profile: {
role: "Admin",
preferences: {
theme: "dark",
notifications: { email: true, sms: false }
}
},
tags: ["developer", "editor"]
};
// Partial match on deeply nested properties
const source = {
profile: {
preferences: {
theme: "dark"
}
},
tags: ["developer"]
};
console.log(_.isMatch(user, source)); // trueIn this example:
- Top-level properties like
idandnameare ignored because they are not insource. - Inside
profile.preferences, onlythemeis verified;notificationsis ignored. - For
tags, index0("developer") matches, and extra indices in the target array do not cause a failure.
Key Behavioral Nuances
- Order of Array Elements: Array matching depends on
index positions. A source of
['b']will not match a target of['a', 'b']because index0does not match. undefinedValues: If a property insourceexplicitly has the valueundefined, the target must also contain that property with anundefinedvalue. A missing property on the target will not match an explicitundefinedon the source.isMatchvs.isEqual: While_.isEqualdemands an exact 1-to-1 match of all keys and values across both objects,_.isMatchrequires only that the source is a structural subset of the target.