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

Photo by Rahul Mishra on Unsplash

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.

--

--