Lodash result Execution Context Explained

This article explores how Lodash's _.result method handles function invocation, focusing specifically on the execution context (this) assigned when a resolved property is a function. Readers will learn the precise binding mechanism _.result uses for both top-level and deeply nested object properties, complete with practical code demonstrations.

The Execution Context of _.result

When _.result(object, path, [defaultValue]) resolves a target property to a function, it dynamically binds the execution context (this) to the immediate parent object of that function. Rather than binding to the global scope or leaving this undefined, Lodash ensures that the method executes as if it were called directly as a method of the object in which it resides.

This behavior mimics standard JavaScript property access invocations (e.g., parent.method()), allowing methods that rely on other sibling properties to function properly.

Shallow Property Access

When the property path is a single key directly on the source object, the execution context is the source object itself:

const user = {
  name: 'Alex',
  greet: function() {
    return `Hello, my name is ${this.name}`;
  }
};

_.result(user, 'greet');
// => "Hello, my name is Alex"

In this case, this inside greet references user.

Nested Property Access

When querying deeply nested paths, _.result navigates down the object hierarchy and binds this to the object immediately preceding the target property, not the root object:

const company = {
  name: 'Tech Corp',
  department: {
    name: 'Engineering',
    getName: function() {
      return this.name;
    }
  }
};

_.result(company, 'department.getName');
// => "Engineering"

Here, this is bound dynamically to company.department, meaning this.name resolves to 'Engineering' rather than 'Tech Corp'.

Internal Implementation

Internally, Lodash achieves this by slicing the target path to find the parent node:

  1. It traverses the path up to the second-to-last segment to retrieve the parent object.
  2. It retrieves the target function located at the final path segment.
  3. It invokes the function using Function.prototype.call, passing the resolved parent object as the first argument:
    value.call(parent);

Exceptions to Dynamic Context Binding

The dynamic binding applied by _.result respects standard JavaScript context rules and will not override contexts under two conditions: