Lodash _.isMatchWith() method
What you’ll learn
- How
_.isMatchWith(object, source, customizer)layers rules on top of partial matching. - When returning
true,false, orundefinedfrom the customizer. - Patterns like synonym strings, numeric tolerance, or mixed strict and loose fields.
- How this compares with
_.isMatchand_.isEqualWith.
Prerequisites
You already understand _.isMatch and writing small comparator functions.
- You know partial object equality differs from full deep equality.
- Try-it labs load lodash from the CDN.
Overview
Reach for _.isMatchWith when acceptance tests need fuzzy equality on some fields (rounded scores, greeting synonyms, date truncation) while still enforcing strict lodash semantics elsewhere.
Still partial
Only keys in source participate—extras on object are ignored.
Per-value hooks
Customizer decides tricky pairs before default depth kicks in.
Undefined = default
Explicit undefined keeps lodash’s recursive equality behavior.
Syntax
_.isMatchWith(object, source, [customizer]) - object: value to inspect.
- source: required subset of properties and expected values.
- customizer (optional): comparator invoked as
(objValue, srcValue, key, object, source); omit or pass non-functions for default matching. - Returns:
truewhen every source path matches subject to your overrides.
Synonym strings (lodash docs pattern)
Treat “hi” and “hello” as interchangeable greetings while everything else stays strict.
import isMatchWith from "lodash/isMatchWith";
function isGreeting(value) {
return /^h(?:i|ello)$/.test(value);
}
function greetingCustomizer(objValue, srcValue) {
if (isGreeting(objValue) && isGreeting(srcValue)) {
return true;
}
}
var object = { greeting: "hello" };
var source = { greeting: "hi" };
console.log(
"custom: " + isMatchWith(object, source, greetingCustomizer) + "\n" + // true
"plain: " + isMatchWith(object, source) // false
); Numeric tolerance
Allow floating-point drift when comparing a measured value to an expected baseline.
import isMatchWith from "lodash/isMatchWith";
function epsilonCustomizer(objValue, srcValue, key) {
if (key === "latencyMs") {
return (
typeof objValue === "number" &&
typeof srcValue === "number" &&
Math.abs(objValue - srcValue) < 0.5
);
}
}
console.log(
"close: " +
isMatchWith({ latencyMs: 10.2 }, { latencyMs: 10.4 }, epsilonCustomizer) + "\n" + // true
"far: " +
isMatchWith({ latencyMs: 12 }, { latencyMs: 10.4 }, epsilonCustomizer) // false
); Mixed strict and loose keys
Return undefined for keys you do not customize so lodash applies ordinary equality.
import isMatchWith from "lodash/isMatchWith";
function scoreCustomizer(objValue, srcValue, key) {
if (key === "score") {
return (
typeof objValue === "number" &&
typeof srcValue === "number" &&
Math.abs(objValue - srcValue) < 1
);
}
}
console.log(
"bothOk: " +
isMatchWith(
{ score: 10, id: 1 },
{ score: 10.5, id: 1 },
scoreCustomizer
) + "\n" + // true (score fuzzy + id strict)
"idFails: " +
isMatchWith(
{ score: 10, id: 2 },
{ score: 10.5, id: 1 },
scoreCustomizer
) // false
); 📋 _.isMatchWith vs related APIs
| API | Behavior |
|---|---|
_.isMatchWith(obj, src, fn) | Partial shape match with optional per-value overrides. |
_.isMatch(obj, src) | Same subset rules; always lodash default comparisons. |
_.isEqualWith(a, b, fn) | Full-structure equality with customizer—not subset-based. |
| Predicate wrapper | Use (obj) => _.isMatchWith(obj, source, fn) with _.filter or guards—lodash does not ship a separate matchesWith helper in 4.x. |
Pitfalls to avoid
Accidental looseness
Returning true too eagerly weakens guarantees—scope checks to explicit keys or types.
Customizer depth
Nested objects still recurse; ensure overrides behave correctly for child values.
Hot paths
Heavy customizers on huge trees add cost—profile before micro-matching everywhere.
❓ FAQ
Summary
- Purpose: partial matches with hookable comparisons per property pair.
- Remember:
undefineddefers to lodash;true/falsedecide outright. - Next: explore more on Lodash _.isNaN().
When the customizer returns undefined, lodash continues with its normal deep comparison for that pair—so you only override the cases you care about.
6 people found this page helpful
