Understanding Call, Apply and Bind by creating them - Javascript
Tags: javascript, webdev
Published: 2020-08-30 02:04:27

Creating stuff with the tools that you are using is pretty fun but you know what's amazing is when you know how to create the tools that you are using. So I started to experiment with small javascript methods such as call, apply, and bind. I even created react virtual dom and Git but I will leave that for another post. So let's get into it starting with the Call method!

##The JavaScript call() Method

The call method allows us to change what the **this** value of a function is point to eg. 
```javascript
function greeting(lan) {
	console.log(`My name is ${this.name} and I am learning ${lan}`);
}

let Shanoy = {
	name: "Shanoy",
};

let Lamar = {
	name: "Lamar",
};
```

If we were to call the greeting function the **this.name** would point to the Global window object and search for a property called **name**. But that's not what we want. We want it to point to an object that we specify which is Lamar and Shanoy

```javascript
greeting.call(Shanoy, "React"); 
//return My name is Shanoy and I am learning React


greeting.call(Lamar, "Vue"); 
//return My name is Lamar and I am learning Vue
```
Did you see that? The call method is now pointing to **Lamar** and **Shanoy** Object. Now that you understand call lets implement our own which is quite simple

```javascript
Object.prototype.calling = function (obj, ...args) {
	const newObj = Object.assign({}, obj, { newMethod: this });
	return newObj.newMethod(...args);
};

greeting.calling(Shanoy, "React");
//return My name is Shanoy and I am learning React

greeting.calling(Lamar, "Vue");
//return My name is Lamar and I am learning Vue
```
So what we are doing above is creating a new method call **calling** to work on every Object that's why we place it on the global object prototype. It takes two arguments: 
1. Our Object that we want the **this** value to change to 
2. The rest of the arguments that were specified on the greeting function

The three dots(...) in front of the **args** is a spread operator that turns all arguments after the first into an array


Next, we need to create a new object combine with the object we want the **this** value to change to and the current **this** value which is the greeting function. There is no way we can save a function in an object without placing it with a key pair value  that's why we place it on the newMethod key
```javascript
const newObj = Object.assign({}, obj, { newMethod: this });
```
Final we return the new object that we created and call the newMethod as you can see the greeting function is now point to our 
object that we specify and we spread the arguments out of the array and into our greeting function
```javascript
return newObj.newMethod(...args);
```
##The JavaScript apply() Method

Apply is similar to call the only difference is if the second argument that your passing in is an array and not a string 

```javascript
Object.prototype.applying = function (obj, args) {
	const newObj = Object.assign({}, obj, { newMethod: this });
	if (!Array.isArray(args)) {
		throw new Error("Second argument should be an Array");
	}
	return newObj.newMethod(...args);
};
```

Do you notice that we are not spreading the **args** parameter that's because we are expecting an array as an argument. 

```javascript
greeting.applying(Shanoy, ["React"]);
//return My name is Shanoy and I am learning React
```

##The JavaScript bind() Method
The bind method is kind of similar to call and apply but it returns a function and we would have to invoke it for it to run eg.
```javascript
let greet = greeting.bind(Shanoy);
greet("golang");
```
We change the **this** value to Shanoy object and save the return function in the greet variable to call at a later date and that's the power of the bind method. Here's our implementation of it

```javascript
Object.prototype.binding = function (obj) {
	const newObj = Object.assign({}, obj, { newMethod: this });
	return function () {
		return newObj.newMethod(...arguments);
	};
};
```
Did you see what we are doing differently instead of return the newobj we return a function. When we return a function it won't run unless we invoke it 

```javascript
let greet = greeting.binding(Shanoy);
greet("golang");
// return My name is Shanoy and I am learning golang


let lamarGreet = greeting.binding(Lamar);
lamarGreet("Flutter");
// return My name is Lamar and I am learning Flutter
```
##A quick run down of what each method does
1. Call invokes the function immediately and allows you to pass in arguments one by one
2. Apply invokes the function immediately and allows you to pass in arguments as an array.
3. Bind returns a new function, and you can invoke/call it anytime you want by invoking a function.


Thank you guys for reading my post it was my first post so I hope you guys learned something new I know I did. I just learn a few MarkDown syntaxes.