Lodash invokeMap with Path Array Method Names

The _.invokeMap method in Lodash allows developers to invoke a specific function on each element in a collection, returning the results in a new array. When the method target is defined as an array of path segments rather than a simple string, Lodash traverses nested object structures to locate the method, properly preserves the execution context (this), passes any provided arguments, and gracefully handles missing properties along the path.

Path Normalization and Traversal

When you pass an array of path segments (such as ['nested', 'deeply', 'methodName']) to _.invokeMap, Lodash routes the operation through internal helpers, primarily baseEach and baseInvoke.

For each item in the collection, Lodash processes the segment array using these steps:

  1. Path Division: Lodash identifies the path to the parent object by taking all segments except the last one (using last and initial slices). For example, ['a', 'b', 'c'] is divided into a parent path ['a', 'b'] and the target method name 'c'.
  2. Parent Resolution: Using internal navigation logic identical to _.get, Lodash walks through the object using the parent path segments. If the path array contains only a single element (e.g., ['methodName']), the current collection item itself is treated as the parent object.
  3. Method Retrieval: Lodash accesses the property corresponding to the final segment on the resolved parent object.

Context Preservation and Execution

A critical aspect of providing a path array is preserving the this binding. In JavaScript, invoking an extracted nested function without explicit binding can cause this to default to undefined or the global object.

Lodash handles this automatically:

Safe Navigation and Guarding

If any segment along the path array does not exist, or if the resolved property is not a callable function, Lodash does not throw a TypeError. Instead, it guards the invocation:

Example

const _ = require('lodash');

const users = [
  {
    profile: {
      getName(prefix) {
        return `${prefix} ${this.firstName}`;
      },
      firstName: 'Alice'
    }
  },
  {
    profile: {
      getName(prefix) {
        return `${prefix} ${this.firstName}`;
      },
      firstName: 'Bob'
    }
  },
  {
    // Missing 'profile' branch
    name: 'Charlie'
  }
];

// Invoking using a path segment array
const results = _.invokeMap(users, ['profile', 'getName'], 'User:');

console.log(results);
// Output: ['User: Alice', 'User: Bob', undefined]

In this execution, Lodash navigates to item.profile for each entry, evaluates getName, binds this to item.profile, and passes 'User:' as the argument, safely returning undefined for the entry lacking the nested path.