Interviewer: Write the polyfill of call, apply, and bind in 2 Different Ways.
A Dual Approach to Polyfills: Solving Call, Apply, and Bind in JavaScript
I recently participated in a front-end interview with a major tech giant in India, focused on quick commerce.
During the second round, the interviewer asked me to write polyfills for the call, apply, and bind methods. He mentioned that we would continue the discussion once I had completed the polyfills.
Given my familiarity with how these methods work, I was able to write the polyfills with ease. I’m sharing my insights here, which may assist you in successfully navigating your next interview.
Before we start. 🦖
The thumb rule for writing polyfill, we often use alternate methods to accomplish the polyfill. So don’t be afraid.
In call
polyfil we can use apply.
In apply
polyfill we can use call.
In bind
polyfill we can use either call or apply.
But today we will push the level, and we will write polyfill without using call and apply.
Polyfill of call
call
method we use to invoke a function with the custom value of this
. In short, call
methods decides what would be the value of this
inside the function that is being invoked by call
Syntax:
function.call(object, params1, params2,..... paramsN)
Example without using call:
function show() {
console.log(this.msg);
}
show(); // logs undefined
Example using call:
const obj = {msg: "Called using call"};
show.call(obj); // Called using call
Polyfill, Easy Path:
Function.prototype.myCall = function(objContext, ...args) {
const result = this.apply(objContext, args);
return result;
};
Let’s take a tough route.
Now we know that call
the method invokes a function on the passed object.
And based on this knowledge if we do something like this:
const obj = {
name:'JS'
};
function show() {
console.log(this.name);
}
obj.show = show;
obj.show();
then this might solve our problem, but with the above code, there is an issue.
what if there is a key named show
present in the object?
In this case, we are overriding it.
const obj = {
name:'JS',
show:'No'
};
function show() {
console.log(this.name);
}
obj.show = show; // overriding show Key
obj.show();
To overcome this we can use Symbol, and by using this approach we can easily write polyfill of call
without using apply
Function.prototype.myCall = function(context, ...args) {
context = context || globalThis;
const fnSymbol = Symbol();
context[fnSymbol] = this; // 'this' is the function to be called
// Execute the function and capture the result
const result = context[fnSymbol](...args);
// Delete the temporary property
delete context[fnSymbol];
// Return the result of the function call
return result;
};
Polyfill of apply
Easy Peasy: using call
method
Function.prototype.apply = function(objContext, args) {
const result = this.call(objContext, ...args);
return result;
};
The tough route:
Function.prototype.myApply = function(objContext, args) {
// If context is null or undefined, set it to global object
objContext = objContext || globalThis;
// Create a unique property on the context to avoid overwriting existing properties
const fnSymbol = Symbol();
context[fnSymbol] = this; // 'this' is the function to be called
// Execute the function and capture the result
const result = objContext[fnSymbol](...(args || []));
// Delete the temporary property
delete objContext[fnSymbol];
// Return the result of the function call
return result;
};
Polyfill of bind
bind
function returns a new function, after changing this inside the function, and this change is permanent.
Function.prototype.myBind = function(objectContext, ...restArgs) {
// Save reference to the original function
// this is the function in which we invoke my Bind
// show.myBind();// this will point to show function
const self= this;
return function(...newArgs) {
// Merge the arguments passed to bind with those passed to the new function
return self.apply(objectContext, [...restArgs, ...newArgs]);
};
};
I hope this made you learn something new.