Lodash _.matches() Method

Beginner
⏱️ 8 min read
📚 Updated: Jul 2026
🎯 6 Examples + 3 Try It
Util utilities

What You’ll Learn

By the end of this tutorial, you’ll build reusable partial-match predicates with Lodash’s _.matches() and use them in filter, find, and conditional checks.

01

Core Syntax

_.matches(source) returns a predicate.

02

Partial Match

Only listed keys are compared.

03

Deep Compare

Nested objects match recursively.

04

Filter & Find

Pair with collection methods.

05

Shorthand

Object literals in _.filter.

06

vs conforms

Values vs predicate functions.

What Is _.matches()?

_.matches() creates a predicate function for partial deep comparison. You describe a pattern object (source); the returned function checks whether another object matches every key you listed—nothing more. Extra fields on the target object are ignored.

💡
Beginner tip — partial, not exact

_.matches({ role: 'admin' }) matches { name: 'Bob', role: 'admin', active: true } because role matches. Bob’s other properties are not required in the pattern.

If you have ever written _.filter(users, { age: 30 }), you already used matches semantics—Lodash converts that object shorthand internally. Explicit _.matches() lets you store and reuse the same predicate.

📝 Syntax

Pass a pattern object; receive a predicate function:

javascript
_.matches(source)

Syntax Rules

  • source — plain object describing properties and values to match.
  • Return value — a function (object) => boolean.
  • Partial — only keys in source are checked; extra target keys are allowed.
  • Deep — nested plain objects in source are compared recursively.
  • One-off check — use _.isMatch(object, source) when you do not need a reusable predicate.
javascript
import matches from "lodash/matches";



const users = [

  { id: 1, name: "John", age: 30 },

  { id: 2, name: "Jane", age: 25 },

];



const isThirty = matches({ age: 30 });



_.filter(users, isThirty);

// [{ id: 1, name: 'John', age: 30 }]

⚡ Quick Reference

TaskCode patternNotes
Build predicate_.matches({ role: 'admin' })Reusable function
Filter array_.filter(arr, _.matches(p))Keep matches
Find first_.find(arr, _.matches(p))First match
Inline shorthand_.filter(arr, { age: 30 })Same rules
One-off test_.isMatch(obj, pattern)Immediate boolean
Nested pattern_.matches({ user: { name: 'A' } })Deep partial
Returns
Function

Predicate

Match type
Partial

Listed keys only

Depth
Deep

Nested objects

Category
Util

Matching

🧰 Parameters

What you pass to _.matches() and how the predicate behaves:

source Required

Pattern object. Each own enumerable key in source must match the corresponding value on the object passed to the predicate.

_.matches({ status: "active" })
returned fn Predicate

Invoked as predicate(object). Returns true when all listed keys match; otherwise false.

const ok = isActive(record)
extra keys Allowed

Properties on the target object that are not in source do not affect the result.

{ a: 1, b: 2 } matches { a: 1 }
nested source Deep

Nested plain objects use recursive partial matching—not dot-path strings. Use nested structure in source.

{ meta: { tier: "pro" } }

For matching one property path by string (e.g. 'user.name'), see _.matchesProperty().

Examples Gallery

Practical _.matches() patterns with copy-ready code, sample output, and interactive Try It Yourself labs.

📚 Getting Started

Filter and find records by field values.

Example 1 — Filter by age

Keep users whose age is 30.

javascript
const users = [

  { id: 1, name: "John", age: 30 },

  { id: 2, name: "Jane", age: 25 },

  { id: 3, name: "Alice", age: 35 },

];



console.log(_.filter(users, _.matches({ age: 30 })));

// [{ id: 1, name: 'John', age: 30 }]
Try It Yourself

How It Works

Only age is in the pattern—name and id are not compared.

Example 2 — Find with multiple keys

Match several properties at once for a precise lookup.

javascript
const data = [

  { id: 1, name: "John", age: 30 },

  { id: 2, name: "Jane", age: 25 },

];



const matcher = _.matches({ id: 1, name: "John" });



console.log(_.find(data, matcher));

// { id: 1, name: 'John', age: 30 }
Try It Yourself

How It Works

Every key in the pattern must match. Adding age: 25 would fail for John because his age is 30.

📈 Practical Patterns

Nested data, partial matching, and shorthand forms.

Example 3 — Nested object matching

Deep partial compare on nested plain objects.

javascript
const records = [

  { id: 1, user: { name: "John", age: 30 } },

  { id: 2, user: { name: "Jane", age: 25 } },

];



const nestedMatcher = _.matches({ user: { name: "John" } });



console.log(_.find(records, nestedMatcher));

// { id: 1, user: { name: 'John', age: 30 } }
Try It Yourself

How It Works

Nested user.age is not in the pattern, so 30 vs 25 does not matter—only user.name is checked.

Example 4 — Extra properties still match

Partial matching means unlisted fields are ignored.

javascript
const users = [

  { id: 2, name: "Jane", age: 25, city: "NYC" },

  { id: 3, name: "Alice", age: 35 },

];



console.log(_.filter(users, _.matches({ name: "Jane" })));

// Jane matches — id, age, and city are not required



console.log(_.isMatch(users[0], { name: "Jane" }));

// true — one-off check without building a predicate

How It Works

The old tutorial’s “exact property matching” wording was misleading—matches is intentionally partial, not a full object clone comparison.

🚀 Beyond the Basics

Shorthand syntax and conditional checks.

Example 5 — Object shorthand in filter

Inline matcher objects use the same rules as _.matches().

javascript
const users = [

  { id: 1, name: "John", age: 30 },

  { id: 2, name: "Jane", age: 25 },

];



const explicit = _.filter(users, _.matches({ age: 30, name: "John" }));

const shorthand = _.filter(users, { age: 30, name: "John" });



console.log(explicit);

console.log(shorthand);

// both: [{ id: 1, name: 'John', age: 30 }]

When to use explicit matches

Store const isJohnAt30 = _.matches({ age: 30, name: 'John' }) when the same predicate runs in multiple places. See also _.iteratee().

Example 6 — Conditional logic

Call the predicate directly in an if statement.

javascript
const user = { name: "John", age: 30 };

const isAdmin = _.matches({ role: "admin" });



if (isAdmin(user)) {

  console.log("User is an admin");

} else {

  console.log("User is not an admin");

}

// User is not an admin — no role property

Missing keys fail the match

If a key in the pattern is missing on the object (or undefined without matching), the predicate returns false.

🧠 How _.matches() Works

1

Capture pattern

Lodash stores the source object you pass in.

Setup
2

Return predicate

The new function closes over that pattern for reuse.

Factory
3

Partial deep compare

On each call, every key in source is compared—recursively for nested objects.

Execute
=

true or false

All listed keys match → true. Any mismatch → false.

📝 Notes

  • Matching is partial—only keys in source matter; extra target properties are fine.
  • Nested patterns use nested objects, not dot-path strings like 'user.name'.
  • _.filter(arr, { k: v }) and _.filter(arr, _.matches({ k: v })) behave the same.
  • Use _.isMatch(obj, pattern) for a single immediate check without storing a predicate.
  • For custom validation logic per field (types, ranges), use _.conforms() instead.
  • Next in the series: _.matchesProperty() for path + value matching.

Conclusion

_.matches() turns a pattern object into a reusable predicate for partial deep comparison—ideal for filtering and finding records by field values.

Remember partial semantics, store predicates when you reuse them, and reach for _.conforms() when each field needs custom validation logic.

💡 Best Practices

✅ Do

  • Store _.matches(pattern) when the same filter runs in multiple places
  • Use object shorthand for one-off _.filter / _.find calls
  • Model nested data with nested pattern objects
  • Pair with _.find, _.some, and _.reject
  • Use _.isMatch for single boolean checks

❌ Don’t

  • Expect full object equality—use _.isEqual for that
  • Use dot strings inside matcher objects for nested paths
  • Assume missing pattern keys pass automatically—they must match values
  • Use matches when each field needs a custom predicate—use conforms
  • Mutate source after creating the predicate if you rely on stable rules

Key Takeaways

Knowledge Unlocked

Five things to remember about _.matches()

Use these points when matching objects in Lodash.

5
Core concepts
📄 02

Partial

Listed keys only.

Mechanics
📈 03

Deep

Nested objects.

Structure
📊 04

Filter

Collection ops.

Practical
05

conforms

Custom rules.

Compare

❓ Frequently Asked Questions

_.matches(source) returns a predicate function. When you call it with an object, it returns true if that object partially matches source—a deep comparison on every key listed in source. Extra properties on the object do not fail the match.
_.isEqual(a, b) checks full deep equality between two values. _.matches(source) checks only the keys you list in source—partial match. An object can have many other properties and still match.
Yes. _.filter(users, { age: 30 }) uses the same partial-match rules as _.filter(users, _.matches({ age: 30 })). _.matches() is for storing and reusing the predicate.
Yes. Nested source objects are compared deeply. For example, _.matches({ user: { name: 'John' } }) matches { id: 1, user: { name: 'John', age: 30 } } because the listed nested keys match.
_.matches() compares values with partial deep equality (object patterns). _.conforms() runs custom predicate functions per key—useful for type checks, ranges, and regex tests instead of fixed values.
Use it to filter or find records by fixed field values, build reusable search predicates, and express object-shape checks readably in _.filter, _.find, _.some, and conditional logic.
Did you know?

When you pass a plain object to _.filter or _.find, Lodash converts it through the same matching rules as _.matches(). Explicit _.matches(pattern) is most valuable when you name and reuse that predicate across your codebase.

Practice _.matches() in the Live Editor

Open the Try It editor, run the examples, and build your own object matchers.

Open Try It editor →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful