Call, Bind and Apply - The Trinity
Tags: javascript, beginners, webdev, codenewbie
Published: 2022-05-13 08:26:56

## Table of Contents
1. [Introduction to Call Bind and Apply](#introduction-to-call-bind-and-apply)
2. [Definition](#definition)
3. [Why to use?](#why-to-even-use-these-in-the-first-place)
4. [How to use?](#how-to-use-these-methods)
5. [Summary](#summary)
6. [References](#references)

## Introduction to Call Bind and Apply

When I first came across these terms, I was super confused and clueless. How are these different from each other? Function borrowing!? - What does that even mean?

<img width="100%" style="width:100%" src="https://media.giphy.com/media/gzQ1X1Fk25UwE/giphy.gif">

Here's my attempt to share what I have learned so far!
*Note: This blog assumes you have a basic understanding of[ this ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)keyword.*

-----------
## Definition 
### Function borrowing
> It allows us to use methods of an object on another object without having to create a copy or rewrite it in several places.

### call()
> call() is used to invoke a method. 
syntax- `call(thisArg, arg1,arg2, ...., argN)`

### apply()
> apply() is also used to invoke a method.
 It is similar to call(), with the only difference that call() takes all the arguments individually, while apply() take array like object as an argument.
syntax- `apply(thisArg,[arg1,agr2,...,agrN])`

### bind()
> bind() creates a new function which can be invoked somewhere later when needed.
syntax- `bind(thisArg, arg1,arg2, ...., argN)`

## Why to even use these in the first place?

 Let's take an example to understand when and why to use these methods. 
* First things first: We know how to access a normal Object property.

```
const userList = {
  user: "Aditi",
  age: 25
};
//accessing the properties
console.log(`Hi ${userList.user}. How's ${userList.age} 
treating you?`);

// output
// Hi Aditi. How's 25 treating you?
```

Now let's suppose we have a method inside userList. 
```
const userList = {
  user: "Aditi",
  age: 25,
printDetails: function(){
console.log(`Hi ${this.user}. How's ${this.age} 
treating you?`);
}
};
// output
// Hi Aditi. How's 25 treating you? 
```
Now if we call `userList.printDetails();` we get the same output.

Now suppose we have another object `adminList` and we want to access the `printDetails()` method. What to do now? 
You can say we can create another object with a different value and copy the printDetails() method to access it. 
```
const adminList = {
  user: "Ananya",
  age: 26,
printDetails: function(){
console.log(`Hi ${this.user}. How's ${this.age} 
treating you?`);
}
};

// output
// Hi Ananya. How's 26 treating you? 
```
Sounds good? 
Now suppose your app grows, and you have more numbers of objects. You would need to copy and repeat this method in all your objects. There also might be a case where the number of methods increases too. 
So, to avoid repetition we should use these function borrowing methods! 

## How to use these methods?
Now let's understand how to solve the above-discussed problem. 
 
### Using call()
```
const userList = {
  user: "Aditi",
  age: 25,
  printDetails: function (city, country) {
    console.log(`Hi ${this.user} from ${city}, ${country}.
    How's ${this.age} treating you?`
    );
  }
};
const adminList = {
  user: "Ananya",
  age: 26
};

// borrowing printDetails() using call()

userList.printDetails.call(adminList, "Patna", "India");

// output
// Hi Ananya from Patna, India. How's 26 treating you? 

```
### Using apply()
```
const userList = {
  user: "Aditi",
  age: 25,
  printDetails: function (city, country) {
    console.log(`Hi ${this.user} from ${city}, ${country}.
    How's ${this.age} treating you?`
    );
  }
};
const adminList = {
  user: "Ananya",
  age: 26
};

// borrowing printDetails() using apply()

userList.printDetails.apply(adminList, ["Patna", "India"]);

// output
// Hi Ananya from Patna, India. How's 26 treating you? 
```
### Using bind()
```
const userList = {
  user: "Aditi",
  age: 25,
  printDetails: function (city, country) {
    console.log(`Hi ${this.user} from ${city}, ${country}.
    How's ${this.age} treating you?`
    );
  }
};
const adminList = {
  user: "Ananya",
  age: 26
};

// borrowing printDetails() using bind()

const printAdminDetails = userList.printDetails.bind(
  adminList,
  "Patna",
  "India"
);

printAdminDetails();

// output
// Hi Ananya from Patna, India. How's 26 treating you? 
```
So, without having to copy the `printDetails()` inside the second object `adminlist` we were able to access the method with the help of call(), apply() and bind().

-----------------
## Summary
* call(), bind() and apply() are used to borrow methods of a object. 
* call() and apply() are invoked and executed immediately.
* The difference between call() and apply() is the way they take arguments. call() takes all arguments separately while apply() takes arguments in an array.
* bind() creates a new function which is executed later when invoked.

-----------------
### References
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply