Lodash _.invoke() method

Beginner
⏱️ 7 min read
📚 Updated: May 2026
🎯 3 Code examples
🚀 3 Try-it labs
Lodash

What you’ll learn

  • How _.invoke(object, path, [...args]) calls a method at a nested path and returns its result.
  • Why this inside the invoked method is the method’s direct parent on the resolved path.
  • How _.invoke differs from the often-confused _.invokeMap (the collection variant).
  • How missing paths are handled safely (no throw—just undefined).

Prerequisites

Comfortable with _.get()-style nested paths and how this works in method calls.

  • Single object, single call: not a batch operation. For batches use _.invokeMap.
  • Path syntax: dotted strings, bracket strings, or array paths—same rules as _.get.
  • Missing-path safe: missing method paths return undefined. Guard paths that may resolve to non-functions.

Overview

_.invoke resolves a path on an object, finds a function at the end, and calls it. The function is invoked with this set to the path’s parent, exactly like a regular dotted call would have done—but without the TypeError when something in the path is missing.

Path-based call

String or array path resolves to the function; remaining arguments are forwarded to it.

Missing-path safe

If the method path is missing, you get undefined back instead of a missing-property crash.

Correct this

No manual binding needed—the parent of the path is automatically the receiver.

Syntax

javascript
_.invoke(object, path, [...args])
  • object: the source to walk. null or undefined returns undefined.
  • path: string ("a.b[0].do") or array (["a", "b", 0, "do"]) describing where the method lives.
  • ...args: arguments forwarded to the method when it’s called.
  • Returns: the method’s return value, or undefined when the method path is missing. If the path exists but is not callable, guard it first.
1

Call a method at a nested path

The canonical use case—walk a string path, call the function you find, get back the result. Note how this is automatically the path’s parent object.

javascript
import invoke from "lodash/invoke";

const data = {
  a: [{
    b: {
      c: [1, 2, 3, 4, 5]
    }
  }]
};

invoke(data, "a[0].b.c.slice", 1, 3);
// -> [2, 3]
//    `this` is data.a[0].b.c when slice runs.

invoke(data, ["a", 0, "b", "c", "join"], "-");
// -> "1-2-3-4-5"

invoke(data, "a[0].b.c.reverse");
// -> [5, 4, 3, 2, 1]   (reverse mutates the source array)
Try it Yourself
2

Automatic this binding

When the method reads this, it sees the path’s parent. That is what makes _.invoke different from calling the function in isolation.

javascript
import invoke from "lodash/invoke";

const user = {
  name: "Ada",
  profile: {
    fullName: "Ada Lovelace",
    toJSON() {
      return { name: this.fullName };
    }
  }
};

invoke(user, "profile.toJSON");
// -> { name: "Ada Lovelace" }
//    `this` was user.profile.

// For comparison, call the function with the wrong receiver:
const fn = user.profile.toJSON;
fn.call({});
// -> { name: undefined }   (this.fullName is now undefined)
Try it Yourself
3

Missing paths, guarded non-functions, batch operations

Three behaviours to remember: missing method paths return undefined, existing non-function values should be guarded before calling, and _.invoke is not the batch variant.

javascript
import invoke from "lodash/invoke";
import invokeMap from "lodash/invokeMap";
import get from "lodash/get";

const partial = { name: "Bob" };

invoke(partial, "greet");
// -> undefined   (no method, no crash)

invoke(partial, "name.toUpperCase");
// -> "BOB"      (works because strings have methods)

const maybeLength = get(partial, "name.length");
typeof maybeLength === "function" ? invoke(partial, "name.length") : undefined;
// -> undefined  (guarded because length is a number, not a function)

// Need to call greet() on every user? That's _.invokeMap:
const users = [
  { greet() { return "Hi from A"; } },
  { greet() { return "Hi from B"; } }
];

invoke(users, "greet");
// -> undefined   (users is an array; users.greet doesn't exist)

invokeMap(users, "greet");
// -> ["Hi from A", "Hi from B"]   (this is what we wanted)
Try it Yourself

📋 _.invoke vs related helpers

Topic_.invoke_.invokeMap_.getDirect call
InputSingle objectCollection (array or object)Single objectAnything
What it doesCalls one methodCalls the method on each elementReads a valueCalls one method
Missing-path safeYesYesYesNo
Preserves thisYes (auto)Yes (per element)N/AYes (manually)
ReturnsMethod resultArray of resultsResolved valueWhatever you wrote

Reach for _.invoke when a single dynamic path may not exist. Reach for _.invokeMap when you have many elements that all share the same method name. Reach for _.get when you don’t need to call anything.

Pitfalls to avoid

Confusion

Not a batch helper

It's tempting to pass an array as the first argument. That calls a method on the array, not on each element. Use _.invokeMap for collections.

Dotted keys

Literal dots in keys need array paths

invoke(obj, "x.y.do") resolves three segments. Use ["x.y", "do"] if "x.y" is one literal key.

Untrusted input

Don’t feed user-supplied paths blindly

A dynamic path can resolve to dangerous functions on the prototype chain. Validate against an allow-list before invoking.

Side effects

Methods can still mutate

_.invoke doesn’t isolate the call—methods like Array.prototype.reverse still mutate the underlying array.

❓ FAQ

It resolves a nested path on an object, expects to find a function there, calls it with the supplied arguments, and returns the result. Think of it as _.get plus a function call in one step.
_.invoke operates on a single object and calls one method. _.invokeMap operates on a collection (array or object) and calls the same method on each element. The old documentation often confuses these two—_.invokeMap is what you want for batch calls.
Just like a normal method call, `this` refers to the immediate parent of the method along the resolved path. So _.invoke(user, 'profile.toJSON') calls toJSON with `this === user.profile`.
A missing method path returns undefined. If the path exists but resolves to a non-function value, Lodash can throw a TypeError because it still tries to call that value. Guard dynamic paths with _.get and typeof value === 'function' when callability is uncertain.
Yes. Both string paths ("a.b[0].do") and array paths (["a", "b", 0, "do"]) are supported. Use the array form when a key literally contains dots or brackets.
Any arguments after the path are forwarded to the invoked method: _.invoke(obj, 'items.slice', 1, 3) becomes obj.items.slice(1, 3).

Summary

Did you know?

_.invoke calls one method at a path on one object. If you want to call the same method on every element of a collection, that’s a different helper—_.invokeMap.

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.

5 people found this page helpful