call(), apply() and bind() in Javascript
Tags: beginners, javascript, tutorial, webdev
Published: 2020-08-22 09:07:44

Hi there!

I'm back again with a new javascript tutorial. `call()`, `bind()` and `apply()` - you might have seen at least one of these three methods if you've spent quite some time in the Javascript realm. Well, maybe you're not using them that often in your day to day work but these are among most frequently asked questions in any Javascript interview.

Today is the day you learn them. :muscle:

In Javascript, functions are objects. Objects can have properties and methods. So, with every function, we get these three methods.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2ezttkgxje73vx7ev2dw.PNG)


BUT... before starting let's revisit `this` in case of functions. Believe me, that's 80% of the game.

When executing a function, `this` is determined by how a function is called(runtime binding).

```javascript
const person = {
  firstName: 'Sanjeev',
  lastName: 'Sharma',
  age: 22,
  getIntro: function() {
     console.log(`${this.firstName} ${this.lastName} is ${this.age} years old.`);
  }
}

person.getIntro(); // "Sanjeev Sharma is 22 years old."

function randomFunc() {
  console.log(this);
}

randomFunc(); // window object
```


In a method: `this` refers to the **owner** object.
In a function(sloppy mode):  `this` refers to **global** object.
In a function(strict mode): `this` is **undefined**. 

That's enough knowledge for `this`.article. :wink:


## call()
According to MDN:
> The call() method calls a function with a given `this` value and arguments provided individually.

In simple terms, you decide what will be `this` inside a function when calling it.

Let's understand this with a very simple example.
```js
function personIntro() {
  console.log(`${this.firstName} ${this.lastName}`);
};

const person1 = {
  firstName: 'Sanjeev',
  lastName: 'Sharma'
};

personIntro(); // Output 1: undefined undefined

personIntro.call(person1); // Output 2: Sanjeev Sharma

personIntro.call({ firstName : 'Harry', lastName : 'Potter' }); // Output 3: Harry Potter
```

We have a function `personIntro()` that will try to access `this` and console `firstName` and `lastName`. We have three outputs:
1. We didn't use the `call()` method, so `this` by default will refer to `window` object. `window` object doesn't have any properties like `firstName` or `lastName`. Hence, we get `undefined undefined`.
2. This time we use `call()` and pass an object that has the required properties. `this` will now be `person`. Hence, we get a favorable output `Sanjeev Sharma`.
3. It's same as above, just trying to prove how `call()` works. :stuck_out_tongue_closed_eyes:


You can also pass additional arguments in `call()`:
```js
function personIntro(city, state) {
  console.log(`${this.name} is from ${city}, ${state}`);
};

const person = {
  name: 'Max',
  age: 26
}

personIntro.call(person, 'Los Angeles', 'California'); // Output: Max is from Los Angeles, California
```

So, `call()` a function with `this`. :eyes:


## bind()
According to MDN:
> The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

Ugh, too much information to process at once. But since now we understand `call()`, let's use that knowledge to understand `bind()`.

```js
function getPerson(person) {
  console.log(`${ person } is from ${ this.state }.`);
}

getPerson.call({ state : 'California' }, 'Max'); // Output 1: Max is from California.

const personFromCalifornia = getPerson.bind({ state : 'California' });

personFromCalifornia('Max'); // Output 2: Max is from California.
personFromCalifornia('Ben'); // Output 3: Ben is from California.
```

We made a function `getPerson()` that is trying to access `this`. There are two outputs:
1. We use `call()` and pass `{ state : 'California' }`(first argument) to be our `this`. The second argument will be `person`.
2. We try to get the same output as 1 using `bind()`. Using `bind()` we can bind a `this` value to some function and get another function in return. In our case, we bind it with `{ state : 'California' }` and store the returned function in `personFromCalifornia`. Now, when we call `personFromCalifornia`, we just need to pass `person` argument. It will already have a `this` value.
3. Just calling the same function again with a different `person`.


So, what are the differences b/w `call()` and `bind()`?
1. `call()` gets invoked immediately whereas `bind()` returns a function that we can invoke later.
2. `call()` takes additional arguments but `bind()` does not.
3. `call()` doesn't make a copy of the function unlike `bind()`.

Phewww! We're almost done. :sleepy:


## apply()
According to MDN:
> The apply() method calls a function with a given this value, and arguments provided as an array (or an array-like object).

It's exactly the same as `call()`, just with a subtle difference.

```js
function sum(num1, num2) {
  console.log(this + num1 + num2);
}

sum.call(2, 3, 4); // Output: 9
sum.apply(2, [3, 4]); // Output: 9
``` 

`call()` takes argument individually but `apply()` takes them as an array. :satisfied: That's it.


THE END. :raised_hands:

Connect with me on [LinkedIn](https://www.linkedin.com/in/thesanjeevsharma), [GitHub](https://www.github.com/thesanjeevsharma) or [Twitter](https://www.twitter.com/thesnjvsharma).

Thank You. :wave: I hope you learned something, today. :pray: