Javascript call(), apply(), bind() methods & their polyfills
Tags: javascript, polyfill, interview, es6
Published: 2022-01-30 11:11:41

In this article, I'll be explaining the call, apply & bind methods & how to write their polyfills. These three polyfills are very commonly asked questions in a javascript interview.

Let's get started with an example to understand the need of these methods & then we'll jump on their implementations.

Look at the below code, we have a **person** object & a **printName** method.

```
let person = {
  firstname: "Kirtesh",
  lastname: "bansal"
}

let printName = function (country) {
  console.log(this.firstname + " " + this.lastname + " from " 
  + country);
}
```
As you see the person object is very generic object & we can have multiple object of same type with different values. Here, I'm using **this** keyword in **printName** method. If you are not familiar with it. Don't worry. we'll cover it later. 

Now, we want to perform a **printName** method for each person object. 
 
How can we do that?

First option is that, we add the **printName** method to each object & call it as shown below.

```
let person = {
  firstname: "Kirtesh",
  lastname: "bansal",
  printName : function (country) {
             console.log(this.firstname + " " + this.lastname 
             + " from " + country);
             }    
}

person.printName("India");

Output: 
"Kirtesh bansal from India"
```
If you see the above code. you will realise that we are duplicating the **printName** method for each object. It doesn't seem to be a good practise. That is the reason, I've defined **printName** method as a seperate method in the first code block.

Now, What?

Javascript provides us three methods to handle such cases without duplicating code. 

**1. call(object, arguments)** - invokes the function on passed object along with passed arguments if there 
**2. apply(object, [arguments])** - invokes the function on passed object along with passed array of arguments if there
**3. bind(object, arguments)** - returns a new function with referencing passed object and arguments

Let's start with first the method.

#1. call method

**call** method invokes the function by taking the object on which the method has to be executed as first argument and accepts arguments which can be passed in that method like country in printName method.

It becomes equal to `person.printName("India")`. Where in the **printName** method **this** keyword refers to the person object. As **this** always refers to left side of the `.` on which method is being called. You can check this [link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) to know more about **this** keyword.

```
let person = {
  firstname: "Kirtesh",
  lastname: "bansal"
}

let printName = function (country) {
  console.log(this.firstname + " " + this.lastname + " from " 
  + country);
}

printName.call(person, "India");

Output: 
"Kirtesh bansal from India"
```
Here, We've attached **call** method to **printName** function where the printName method is called for person object therefore it takes the value of firstname & lastname from it & take "India" as parameter for country argument and results the above output.

#2. apply method

**apply** method is very simillar to the **call** method but the only difference is that **call** method takes the argumetns as comma seperated values where as **apply** method takes an array of arguments. If we write the apply method implemetation of the above code. It'll be like this.

```
let person = {
  firstname: "Kirtesh",
  lastname: "bansal"
}

let printName = function (country) {
  console.log(this.firstname + " " + this.lastname + " from " 
  + country);
}

printName.apply(person, ["India"]);

Output: 
"Kirtesh bansal from India"
```  
Here, we replaced **call** with **apply** method & passed the  argument in an array.

let's move to last method.

#3. bind method

**bind** method is simillar to the **call** method but the only difference is that **call** method invokes the function but incase of **bind** it returns a new function which can be invoked later. let's implement **bind** method.

```
let person = {
  firstname: "Kirtesh",
  lastname: "bansal"
}

let printName = function (country) {
  console.log(this.firstname + " " + this.lastname + " from " 
  + country);
}

let newPrintName = printName.bind(person, "India");
newPrintName();

Output: 
"Kirtesh bansal from India"
```  
If you see the above code we have attached the **bind** method to **printName** & stored it into a new variable called **newPrintName**. 

Now, we can call the **newPrintName** any time later in code & it will result in the same output.

Now, let's write the polyfills for all the three methods.

I'll be using Javascript prototype inheritance to write the pollyfills. To make the pollyfills available to all functions.

If you look at the all three methods. They are applied on a function so we will add our polyfill method to **Function** prototype.

You can read about prototype [here](https://javascript.info/prototypes).

let's start with **call** method polyfill. 

```
let person = {
  firstname: "Kirtesh",
  lastname: "bansal"
}

let printName = function (country) {
  console.log(this.firstname + " " + this.lastname + " from " 
  + country);
}

Function.prototype.mycall = function(obj,...args){ 
    let sym = Symbol();                                     
    obj[sym] = this;
    let res = obj[sym](...args)
    delete obj[sym];
    return res;
}
 
/*
Note: Applying mycall method to printName function so this
will be equal to printName inside mycall function as 
printName is on the left side of the '.' 
*/

printName.mycall(person, "India");

Output: 
"Kirtesh bansal from India"
```
Here, I've user **Function.prototype** to make **mycall** method to be available for all the functions & assign it a new function. 

Same as **call** method **mycall** method takes object on which the method has to be invoked as first argument followed by rest of the arguments need to be passed to the function. 

Now, let's understand the inner implemetation of the function. 

Inside the **mycall** function we've created a symbol **sym** to create a unique property on the passed object to prevent existing property overwritten.

Now, On passed object added **sym** property & assigned the **this** keyword to it. which is refering to the **printName** function.

In the next line, We call the function by passing the remaining arguments & store it's response in a new variable **res**. After this, we delete the newly created property **sym** from the passed object as it do not exist on the object outside this function and then we return the response of the object. 

So, finally we have created our first polyfill and it results the same.

Let's jump on the apply method polyfill.

As we have seen thay **apply** is very simillar to the **call** method just it takes array of arguments instead of take comma seperated list of arguments. Therefore, the implementation for **apply** remains same as **call** method with a minor change.

```
let person = {
  firstname: "Kirtesh",
  lastname: "bansal"
}

let printName = function (country) {
  console.log(this.firstname + " " + this.lastname + " from " 
  + country);
}

Function.prototype.myapply = function(obj,...args){
  let sym = Symbol();                                     
  obj[sym] = this;
  let res = obj[sym](...args[0]); 
  delete obj[sym];
  return res;
}

printName.myapply(person, ["India"]);

Output: 
"Kirtesh bansal from India"
```

If you see the above code the implementation steps are same but when we invoke the function on object instead of passing **...args** directly as argumetns. we'll pass the 0th index of **args** using rest operator because rest operator '...' represents arguments array & in this array we've our passed arguments array at 0th index so will pick that array & spread that into the function.

Let's write the final bind method polyfill.

If we recall from bind method implementation. we know that it is same as **call** but instead of invoking the function return new function. Let's see the implementation.

```
let person = {
  firstname: "Kirtesh",
  lastname: "bansal"
}

let printName = function (country) {
  console.log(this.firstname + " " + this.lastname + " from " 
  + country);
}

Function.prototype.mybind = function(object,...args){
  let func = this;
  return function (...args1) {
    return func.apply(object, [...args, ...args1]);
  }
}

let newPrintName = printName.mybind(person, "India");
newPrintName();

Output: 
"Kirtesh bansal from India"
``` 
Here, Same as mycall & myapply methods. We've created a mybind method on Function.prototype & assigned a function to it. This function accepts object & arguments simillar to **bind** method. We already know form the above polyfill implementations that the **this** keyword referes the function. In case on bind, we'll store the **this** on a variable called **func**. since **bind** returns a new function. we'll also return a anonymous function which will act as closure in **mybind** function. Now, this returing function can also accepts arguments which will represent the arguments passed during the invocation of new function returned by **mybind** method. Inside this returning function, we will use **apply** method on the func variable to invoke it for passed object & arguments. In this apply method, we'll create an array to pass arguments & in this array we'll spread the **args** & **args1** to pass all the arguments to the function & store it in a new variable **newPrintName**. 

Later, when we call this **newPrintName**. It results the same. If we pass any argument in **newPrintName** function, **args1** represents these arguments in mybind method.

That's all about call, apply, bind & their polyfills.

Do share your comments and feedback about the article.

Happy learing!