# Mastering the Context: A Guide to this, call, apply, and bind

JavaScript was first designed to work with objects to group related data together. The problem arrived when functions were written to make work with the object.  
Consider building an app that greets the user whenever they open the app, and it should work with every user. To implement functions, either it should be duplicated inside every object. which means maintaing multiple copies, or object should be passed as an argument every time the function is called, making this a exhausting process.  
Neither option keeps the code clean. To solve this problem `this` keyword was introduced. It defined who the current owner is and attach the context whoever is calling the function. `this` gets set at the time a function is called, not when its written, and may result in losing the value on context when a function is passed around.  
That is where `call()`, `apply()`, and `bind()` come in. They were added to the language specifically to give developers control over `this`.

* * *

## What is `this` ?

`this` keyword provides a way to know who called them, and the method and values they contain. When a function is called, `this` to point to the object that made the call.  
Example:

![](https://cdn.hashnode.com/uploads/covers/678b775e773554ab7117f20a/ea64fa93-87c8-4307-97e0-fc51060d18f2.png align="center")

### `this` in Regular Functions

When you write a plain function and call it on its own, without any object in front of it, `this` gets set to the global object (`global` in Node, `window` in browser). In strict mode, it becomes `undefined`.

```javascript
function whoAmI() {
  console.log(this);
}

whoAmI(); // window (browser), global (Node) or undefined (strict mode)
```

The function is called without any object in front, so this points to the global object and nothing meaningful.

### `this` Inside Objects

When a function is defined inside an object and called through that object, `this` refers to the object itself.

```javascript
const user = {
  name: "User",
  greet: function() {
    console.log("Hi, I'm " + this.name);
  }
};

user.greet(); // "Hi, I'm User"
```

Because `user.greet()` is called with `user` as the owner, `this` points to `user`, and `this.name` resolves to `"User"`. Change the caller, and `this` changes with it.

### Why It Breaks When You Copy A Method

Then a method is copied outside the object, stored in a variable, and it is called. `this` loses the context.

```javascript
const user = {
  name: "User",
  greet: function() {
    console.log("Hi, I'm " + this.name);
  }
};

const detached = user.greet;
detached(); // "Hi, I'm undefined"
```

You copied the function reference, but `this` did not come along. When `detached()` runs, there is no object in front of it, so `this` is either `global` or `undefined`, and `this.name` comes back as `undefined`. The same problem happens when you pass an object method into `setTimeout` or an event listener.

![](https://cdn.hashnode.com/uploads/covers/678b775e773554ab7117f20a/db95421e-c352-4d7b-b758-fa795ce477aa.png align="center")

This problem is solved by `call()`, `apply()`, and `bind()`.

* * *

## `call()`: Borrow a Function

`call()` *invokes a function immediately* and allows setting the context for that invocation by adding another argument.

```javascript
// SYNTAX
call(thisArg)
call(thisArg, arg1, arg2,...,argN)

// Example
const user = {
  name: "User",
  greet: function() {
    console.log("Hi, I'm " + this.name);
  }
};

const anotherUser = { name: "Tom" };

// detached() broke because this was lost.
// call() fixes it by telling greet exactly what this should be.
user.greet.call(anotherUser);
// "Hi, I'm Tom"

// You can call it for any object you want
user.greet.call({ name: "Bob" });
// "Hi, I'm Bob"
```

Taking the same `user` object from above, we can borrow its `greet` method and run it for a completely different object.

![](https://cdn.hashnode.com/uploads/covers/678b775e773554ab7117f20a/1f3f8f8f-f873-45d3-a4a4-f42c68298af8.png align="center")

## `apply()`: `call()` With Array Arguments

`apply()` performs exactly like `call()`, the only difference is that we can pass multiple arguments in the form of an array instead of passing them one by one. The array gets unpacked into the function's parameter.  
Take a function that greets a user with a custom message and a language tag. You want to run the same function for two different users, and the arguments you want to pass are already sitting in an array:

```javascript
// SYNTAX
apply(thisArg)
apply(thisArg, argsArray)

// example
function greet(message, language) {
  console.log(message + ", " + this.name + " [" + language + "]");
}

const user1 = { name: "user1" };
const user2 = { name: "user2" };

const args = ["Hello", "EN"];

// call: you pass the args one by one
greet.call(user1, "Hello", "EN");  // "Hello, user1 [EN]"

// apply: you pass the args as an array, same result
greet.apply(user1, args);           // "Hello, user1 [EN]"
greet.apply(user2, args);           // "Hello, user2 [EN]"
```

The `args` is an array which could have been received from API response, form input, or another function output.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Now, the spread operator does the same: <code>greet.call(user1, ...args)</code>. This can replace <code>apply()</code>.</div>
</div>

![](https://cdn.hashnode.com/uploads/covers/678b775e773554ab7117f20a/2ee80e5e-fe17-48ea-8955-2c14b4f44382.png align="center")

## `bind()`: Lock The Context For Later

Unlike `call()` and `apply()`, `bind()` does not run the function at all. It creates and returns a brand new function with `this` permanently locked in, along with the arguments you passed, and this function can be called when needed.

`bind()` can be understood using:

```javascript
const user = {
  name: "User",
  greet: function() {
    console.log("Hi, I'm " + this.name);
  }
};

// The bug: this is lost when greet is detached
const detached = user.greet;
detached(); // "Hi, I'm undefined"

// The fix: bind locks this to user permanently
const fixed = user.greet.bind(user);
fixed(); // "Hi, I'm User"

// Same fix for setTimeout — passes the function, not the result
setTimeout(user.greet, 1000);             // "Hi, I'm undefined"
setTimeout(user.greet.bind(user), 1000); // "Hi, I'm User"
```

Do not use `setTimeout(user.greet(), 1000)` with the parentheses included. That calls `greet` immediately and hands its return value, which is `undefined`, to `setTimeout` instead of scheduling the function itself. When passing functions as callbacks, leave the parentheses off, or use `bind()`.

Another example is:

```javascript
function log(...args) {
  console.log(this, ...args);
}

const boundLog  = log.bind("this value", 1, 2);
const boundLog2 = boundLog.bind("new this value", 3, 4);

boundLog2(5, 6);
// "this value", 1, 2, 3, 4, 5, 6
```

Let's understand it step by step:

**Step 1: the first bind() -** `log.bind("this value", 1, 2)` creates `boundLog`. It locks `this` to `"this value"` and fills the first two arguments as `1` and `2`. Those arguments will always be passed first, no matter how `boundLog` is called later.

**Step 2: trying to re-bind -** `boundLog.bind("new this value", 3, 4)` tries to create a new function with a different `this`. Once `this` is locked by `bind()`, it cannot be changed, and the `"new this value"` gets ignored, because the `bind()` created a wrapper for `boundLog`, and when you try to create a new wrapper which try to provide new `this` gets ignored. Although, the value `3` and `4` gets added to the argument list.

**Step 3: calling boundLog2(5, 6) -** When `boundLog2(5, 6)` runs, the arguments arrive in the order they were locked in across all the bind calls, followed by whatever you pass at call time. That is why the output is `"this value", 1, 2, 3, 4, 5, 6`.

![](https://cdn.hashnode.com/uploads/covers/678b775e773554ab7117f20a/d1bdcc9e-224e-4f19-bf1b-d5c5e5025eee.png align="center")

This behaviour is known as **partial application**.

* * *

## `call()` vs `apply()` vs `bind()`

| Feature | `call()` | `apply()` | `bind()` |
| --- | --- | --- | --- |
| Runs immediately | yes | yes | no |
| Returns | result of the function | result of the function | a new bound function |
| How args are passed | one by one: (a, b) | as an array: (\[a, b\]) | one by one, at bind or call time |
| Can call again later | no, already ran | no, already ran | yes, stored as a function |
| Best used for | borrow and run now | run now with array args | callbacks, event handlers, timers |

* * *

Logically, `this` should depend on where the function is written. Instead, it depends on who calls the function at the moment it runs. This information helps to understand the behaviour of `this` in a better way.

Functionally, both `call()` and `apply()` are ways to execute a function using a given this, and the only difference is whether the arguments are provided individually or all as an array. Each method behaves differently from the other; `bind()` is a completely different concept since it returns a new function with a predefined context to call whenever you desire. This makes `bind()` the best option for use with callbacks or any other code that is related to the event.

* * *

**REFERENCES:**

*   [MDN: The this keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)
    
*   [MDN: Function.prototype.call()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)
    
*   [MDN: Function.prototype.apply()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)
    
*   [MDN: Function.prototype.bind()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)
    
*   [javascript.info: Decorators and Forwarding](https://javascript.info/call-apply-decorators)
    
*   [javascript.info: Function Binding](https://javascript.info/bind)
