Watch 7 video solutions for Call Function with Custom Context, a medium level problem. This walkthrough by NeetCodeIO has 2,934 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Enhance all functions to have the callPolyfill method. The method accepts an object obj as its first parameter and any number of additional arguments. The obj becomes the this context for the function. The additional arguments are passed to the function (that the callPolyfill method belongs on).
For example if you had the function:
function tax(price, taxRate) {
const totalCost = price * (1 + taxRate);
console.log(`The cost of ${this.item} is ${totalCost}`);
}
Calling this function like tax(10, 0.1) will log "The cost of undefined is 11". This is because the this context was not defined.
However, calling the function like tax.callPolyfill({item: "salad"}, 10, 0.1) will log "The cost of salad is 11". The this context was appropriately set, and the function logged an appropriate output.
Please solve this without using the built-in Function.call method.
Example 1:
Input:
fn = function add(b) {
return this.a + b;
}
args = [{"a": 5}, 7]
Output: 12
Explanation:
fn.callPolyfill({"a": 5}, 7); // 12
callPolyfill sets the "this" context to {"a": 5}. 7 is passed as an argument.
Example 2:
Input:
fn = function tax(price, taxRate) {
return `The cost of the ${this.item} is ${price * taxRate}`;
}
args = [{"item": "burger"}, 10, 1.1]
Output: "The cost of the burger is 11"
Explanation: callPolyfill sets the "this" context to {"item": "burger"}. 10 and 1.1 are passed as additional arguments.
Constraints:
typeof args[0] == 'object' and args[0] != null1 <= args.length <= 1002 <= JSON.stringify(args[0]).length <= 105Problem Overview: You need to execute a function using a custom this context, similar to how Function.prototype.call works in JavaScript. The task is to attach the function to a provided object and invoke it so that the object becomes the execution context.
Approach 1: Modify Function Constructor (O(k) time, O(1) space)
This approach mimics how call works internally. Temporarily attach the function to the provided context object, invoke it, then remove it. Because property names may collide with existing keys, a Symbol can be used as a temporary property to guarantee uniqueness. The function is executed using context[tempKey](...args), which forces this to reference the context object. The time complexity is O(k), where k is the number of arguments passed to the function, and the space overhead stays O(1) since only a single temporary property is created.
This method directly demonstrates how dynamic method binding works in JavaScript. Interviewers often prefer this approach because it shows understanding of how functions interact with object contexts and prototype methods.
Approach 2: Using Closures (O(k) time, O(1) space)
A closure-based implementation captures the function and context inside a wrapper function. Instead of modifying the context object, you create a new function that internally invokes the original function while explicitly controlling the execution context. This can be done with apply, bind, or equivalent constructs depending on the language. The closure retains references to the function and context, ensuring that whenever the wrapper runs, the correct this value is used.
The key idea is lexical capture. The wrapper function stores both the target function and the object that should act as its context. When executed, the wrapper forwards the argument list and ensures the correct binding. The runtime cost is still O(k) because the argument list must be forwarded during invocation, while memory usage remains O(1). This pattern appears frequently when working with closures or higher‑order functions.
Closure-based solutions are often easier to reason about in languages that support functional constructs, but they do not demonstrate the internal mechanism of context binding as clearly as the property-attachment technique.
Recommended for interviews: The temporary property approach is typically expected. It shows you understand how this binding works under the hood and how functions behave when attached to objects. Mentioning the closure-based alternative demonstrates deeper knowledge of functional patterns and language design.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Modify Function Constructor | O(k) | O(1) | Best when demonstrating how this binding works internally in JavaScript |
| Using Closures | O(k) | O(1) | When using functional patterns or avoiding mutation of the context object |