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:
- It traverses the path up to the second-to-last segment to retrieve the parent object.
- It retrieves the target function located at the final path segment.
- 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:
- Arrow Functions: If the resolved property is an ES6
arrow function, its execution context is lexically bound at declaration
time and cannot be changed by
_.result. - Explicitly Bound Functions: If the method has
already been bound using
Function.prototype.bind(), the bound instance overrides the parent object supplied by Lodash.