What is call, apply, and bind in JavaScript?
Tags: javascript, programming, beginners, react
Published: 2023-06-02 02:18:55

Do you know how to use `Function.call()`, `Function.apply()`, and `Function.bind()`?

These methods are used to control what the `this` keyword refers to in a function.

## Function.call()
The call() method is explained in MDN below:

> The call() method calls the function with a given `this` value and arguments provided individually.


The syntax of the method is:
```js
call(thisArg)
call(thisArg, arg1)
call(thisArg, arg1, /* …, */ argN)
```

Here is an example code to see what `this` refers to without `call()`.
```js
const message = "Hello from window!";

function test() {
    console.log(this.message);
};

test();
// [LOG] Hello from window!
```
If we do not use `call()`, `this` in the `test` function refers to the global `window` object. Therefore, the `console.log()` in the function displays the message, "Hello from window!".

**Note: If it was an object method, `this` refers to the object.**

Next, let's see what happens when using `call()`.
```js
const message = "Hello from window!";

const testObj = {
  message: "Hello from testObj!"
};

function test() {
    console.log(this.message);
};

test.call(testObj);
// [LOG] Hello from testObj!
```
As you can see, `this` refers to the `testObj` object when we execute the `test` function by the `call()` method with the argument of `testObj`. It means the `this` keyword in the function considers `testObj` as `this`.


### What if the function requires arguments?
If a function requires arguments, you can execute the function with arguments like below:
```js
const testObj = {
  message: "Hello from testObj!"
}

function test(arg1, arg2, arg3) {
  console.log(this.message);
  console.log("arg1: ", arg1, " arg2: ", arg2, " arg3: ", arg3);
}

test.call(testObj, 1, 2, 3);
// [LOG] Hello from testObj!
// [LOG] arg1: 1 arg2: 2 arg3: 3
```

## Function.apply()
The apply() method works similarly to the call() method. But the only difference is the apply() method receives an array of the original function's arguments as an argument.

The syntax of the method is:
```js
apply(thisArg)
apply(thisArg, argsArray)
```

If you want to execute the `test` function by the apply() method, the code will be like this:

```js
const testObj = {
  message: "Hello from testObj!"
}

function test(arg1, arg2, arg3) {
  console.log(this.message);
  console.log("arg1: ", arg1, " arg2: ", arg2, " arg3: ", arg3);
}

test.apply(testObj, [1, 2, 3]);
// [LOG] Hello from testObj!
// [LOG] arg1: 1 arg2: 2 arg3: 3
```
Cool! We can get the same outcome as the previous example code.

## Function.bind()
The `bind()` method works differently compared with the other two methods.
This method returns a copy of the function with provided arguments instead of executing the function immediately.

The syntax of the method is:
```js
bind(thisArg)
bind(thisArg, arg1)
bind(thisArg, arg1, arg2)
bind(thisArg, arg1, arg2, /* …, */ argN)
```

As with the `call()` method, the `bind()` method will receive a value that will be a target of `this` and a number of arguments that will be provided to the original function.

If you want to use the `bind()` method with the `test` function, which we used above, the code will be below:

```js
const testObj = {
  message: "Hello from testObj!"
}

function test(arg1, arg2, arg3) {
  console.log(this.message);
  console.log("arg1: ", arg1, " arg2: ", arg2, " arg3: ", arg3);
}

const boundTestFunc = test.bind(testObj, 1, 2, 3);

boundTestFunc();
// [LOG] Hello from testObj!
// [LOG] arg1: 1 arg2: 2 arg3: 3
```

As you saw, we could get the same log results as the `call()` method. However, you need to execute the new function after making a copy of the original one, like `boundTestFunc()` if you want to call it.

## What is the actual use case?
You may wonder when we use the methods in real-world development. I would honestly say that we do not frequently use these methods on a daily basis.
But, let me share one of the common use cases of the `bind()` method in modern web development.

You will see a code like the one below if you are assigned to work on refactoring the React.js project written with the Class components.
```js
class ExampleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: '' };
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  render() {
    return (
      <input
        type="text"
        value={this.state.value}
        onChange={this.handleChange.bind(this)}
      />
    );
  }
}
```
The `bind()` method is used when passing the `handleChange` method to `onChange` of the `input` element. This is because when calling the method as an event handler in Class components of React.js, `this` will be `undefined`. (`this` should have referred to the object if the `this` keyword is used in methods of the object.)

But, considering recent React.js projects, Functional components are used more often than Class components. Thus, you rarely see Class components and the `bind()` method accordingly, even in React.js projects, unless you are assigned to legacy code maintenance or refactoring.

## Summary
The three methods, `Function.call()`, `Function.apply()`, and `Function.bind()`, are used to control where the `this` keyword refers to.
The `call()` and `apply()` methods are used to immediately execute a function with a certain `this` and arguments. These are used for very similar purposes.
On the other hand, the `bind()` method is used to create a new function, and that was commonly used in Class components in React.js project.