Deep comparison utility that determines if an object contains equivalent property values to a source object
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The isMatch method from the lodash utility library performs deep comparison to determine if an object contains equivalent property values to a source object. Part of lodash's comprehensive collection of JavaScript utilities, this method supports nested objects, arrays, and custom comparison functions.
npm install lodashimport _ from "lodash";
// or
import { isMatch } from "lodash";For CommonJS:
const _ = require("lodash");
// or
const { isMatch } = require("lodash");For AMD:
define(['lodash'], function(_) {
return _.isMatch;
});import _ from "lodash";
const user = { name: 'fred', age: 40, city: 'NYC' };
// Basic property matching
_.isMatch(user, { age: 40 });
// => true
_.isMatch(user, { age: 30 });
// => false
// Multiple property matching
_.isMatch(user, { name: 'fred', age: 40 });
// => true
// Nested object matching
const profile = {
user: { name: 'fred', age: 40 },
preferences: { theme: 'dark' }
};
_.isMatch(profile, { user: { name: 'fred' } });
// => truePerforms deep comparison between an object and a source object to determine if the object contains equivalent property values.
/**
* Performs a deep comparison between `object` and `source` to determine if
* `object` contains equivalent property values. If `customizer` is provided
* it is invoked to compare values. If `customizer` returns `undefined`
* comparisons are handled by the method instead.
*
* @param {Object} object - The object to inspect
* @param {Object} source - The object of property values to match
* @param {Function} [customizer] - The function to customize comparing values
* @param {*} [thisArg] - The `this` binding of `customizer`
* @returns {boolean} Returns `true` if `object` is a match, else `false`
*/
function isMatch(object, source, customizer, thisArg);Usage Examples:
import _ from "lodash";
// Basic matching
const object = { 'user': 'fred', 'age': 40 };
_.isMatch(object, { 'age': 40 });
// => true
_.isMatch(object, { 'age': 36 });
// => false
// Deep nested matching
const nested = {
a: { b: { c: 1, d: 2 }, e: 3 },
f: 4
};
_.isMatch(nested, { a: { b: { c: 1 } } });
// => true
// Array matching searches within arrays
const withArray = { items: ['a', 'b', 'c'], name: 'test' };
_.isMatch(withArray, { items: ['b'] });
// => true (searches for elements within the array)
_.isMatch(withArray, { items: ['a', 'b'] });
// => true (all source elements found in target array)
_.isMatch(withArray, { items: ['b', 'a'] });
// => true (order doesn't matter for element search)
// Empty source always matches
_.isMatch({ a: 1 }, {});
// => true
// Null/undefined object handling
_.isMatch(null, { a: 1 });
// => false
// Undefined value matching requires explicit undefined property
_.isMatch({ a: 1 }, { b: undefined });
// => false (object lacks property 'b')
_.isMatch({ a: 1, b: 2 }, { b: undefined });
// => false (object has property 'b' but value is not undefined)
_.isMatch({ a: 1, b: undefined }, { b: undefined });
// => true (object has property 'b' with undefined value)Allows custom comparison functions for specialized matching logic.
/**
* Custom comparison function signature
* @param {*} value - The value from the object being inspected
* @param {*} other - The value from the source object
* @param {string|number} indexOrKey - The property key being compared (or array index)
* @returns {boolean|undefined} Return boolean for custom comparison, undefined for default behavior
*/
type CustomizerFunction = (value: any, other: any, indexOrKey: string | number) => boolean | undefined;Usage Examples:
import _ from "lodash";
// Custom string matching (case-insensitive)
const object = { greeting: 'hello' };
const source = { greeting: 'HELLO' };
_.isMatch(object, source, function(value, other) {
if (typeof value === 'string' && typeof other === 'string') {
return value.toLowerCase() === other.toLowerCase();
}
return undefined; // Use default comparison for non-strings
});
// => true
// Custom numeric tolerance matching
const measurement = { temperature: 25.1, humidity: 60.3 };
const target = { temperature: 25, humidity: 60 };
_.isMatch(measurement, target, function(value, other) {
if (typeof value === 'number' && typeof other === 'number') {
return Math.abs(value - other) <= 1; // 1 unit tolerance
}
return undefined;
});
// => true
// Using thisArg for context
const config = { tolerance: 0.5 };
_.isMatch(
{ price: 10.3 },
{ price: 10 },
function(value, other) {
if (typeof value === 'number' && typeof other === 'number') {
return Math.abs(value - other) <= this.tolerance;
}
return undefined;
},
config
);
// => true/**
* Deep comparison function interface
*/
interface IsMatchFunction {
(object: any, source: any): boolean;
(object: any, source: any, customizer: CustomizerFunction): boolean;
(object: any, source: any, customizer: CustomizerFunction, thisArg: any): boolean;
}
/**
* Custom comparison function type
*/
type CustomizerFunction = (value: any, other: any, indexOrKey: string | number) => boolean | undefined;
/**
* Lodash namespace containing isMatch
*/
interface LoDashStatic {
isMatch: IsMatchFunction;
}baseIsMatch for comprehensive comparisonfalse immediately if object is null/undefined and source has propertiesThe function is designed to be safe and won't throw errors under normal usage:
false if object is null/undefined and source has propertiesfalse if object lacks a property present in sourcefalse for incompatible types (unless custom comparator handles it)// Filtering arrays of objects
const users = [
{ name: 'john', age: 25, active: true, tags: ['admin', 'user'] },
{ name: 'jane', age: 30, active: false, tags: ['user'] },
{ name: 'bob', age: 25, active: true, tags: ['user', 'premium'] }
];
// Filter by properties
const activeUsers25 = users.filter(user =>
_.isMatch(user, { age: 25, active: true })
);
// => [{ name: 'john', age: 25, active: true, tags: ['admin', 'user'] },
// { name: 'bob', age: 25, active: true, tags: ['user', 'premium'] }]
// Filter by array contents
const adminUsers = users.filter(user =>
_.isMatch(user, { tags: ['admin'] })
);
// => [{ name: 'john', age: 25, active: true, tags: ['admin', 'user'] }]
// Form validation
const formData = {
username: 'john123',
email: 'john@example.com',
age: 25
};
const requiredFields = { username: 'john123', email: 'john@example.com' };
const hasRequiredFields = _.isMatch(formData, requiredFields);
// => true
// API response validation
const apiResponse = {
status: 'success',
data: { id: 1, name: 'Product' },
meta: { timestamp: '2023-01-01' }
};
const expectedShape = {
status: 'success',
data: { id: 1 }
};
const isValidResponse = _.isMatch(apiResponse, expectedShape);
// => true