# The Magic of this, call(), apply(), and bind() in JavaScript

There is a keyword in JavaScript that confuses almost every beginner the first time they run into it. That keyword is `this`. It shows up everywhere, it behaves differently depending on where it is used, and the error messages it produces when something goes wrong are not always the most helpful.

Once we understand `this` properly though, and once we see how `call()`, `apply()`, and `bind()` work alongside it, a lot of JavaScript code that previously looked confusing starts to make complete sense.

* * *

## What Does `this` Mean?

The simplest way to think about `this` is this: it refers to whoever is calling the function at that moment.

It is not fixed. It does not always point to the same thing. It changes based on the context in which a function is called. That is what makes it tricky at first, but also what makes it powerful once we get the hang of it.

Let's start with the most common place we see `this`, inside an object.

* * *

## `this` Inside an Object

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

```javascript
let student = {
  name: "Gurjeet",
  age: 22,
  introduce: function() {
    console.log("My name is " + this.name + " and I am " + this.age + " years old");
  }
};

student.introduce();
// My name is Gurjeet and I am 22 years old
```

When we call `student.introduce()`, JavaScript sets `this` to `student` because `student` is the one calling the function. So `this.name`becomes `student.name`, which is `"Gurjeet"`.

Now let's create another object and see what happens:

```javascript
let teacher = {
  name: "Mr. Singh",
  age: 35,
  introduce: function() {
    console.log("My name is " + this.name + " and I am " + this.age + " years old");
  }
};

teacher.introduce();
// My name is Mr. Singh and I am 35 years old
```

Same function structure, different object, different result. `this` adapts to whoever is calling it. That is the core behaviour to understand.

* * *

## The Problem `this` Creates

Here is where things get interesting. What if we have a function on one object but we want to use it on a different object that does not have that function?

```javascript
let student = {
  name: "Gurjeet",
  age: 22,
  introduce: function() {
    console.log("My name is " + this.name + " and I am " + this.age);
  }
};

let anotherStudent = {
  name: "Priya",
  age: 21
};
```

`anotherStudent` does not have an `introduce` method. We could copy the function over, but that is repetitive and messy. This is exactly the problem that `call()`, `apply()`, and `bind()` solve.

* * *

## call()

`call()` lets us borrow a function from one object and use it on another. We call the function and explicitly tell JavaScript what `this` should be.

```javascript
student.introduce.call(anotherStudent);
// My name is Priya and I am 21
```

We took the `introduce` function from `student` and called it with `anotherStudent` as the context. JavaScript set `this` to `anotherStudent`for that call, so `this.name` became `"Priya"` and `this.age` became `21`.

We can also pass additional arguments after the object:

```javascript
let student = {
  name: "Gurjeet",
  greet: function(city, course) {
    console.log("Hi, I am " + this.name + " from " + city + ", studying " + course);
  }
};

let anotherStudent = { name: "Priya" };

student.greet.call(anotherStudent, "Delhi", "Design");
// Hi, I am Priya from Delhi, studying Design
```

The first argument to `call()` is always the object we want `this` to be. Everything after that gets passed as regular arguments to the function.

* * *

## apply()

`apply()` works exactly like `call()`. The only difference is how we pass the arguments. With `call()` we pass them one by one. With `apply()` we pass them as an array.

```javascript
student.greet.apply(anotherStudent, ["Delhi", "Design"]);
// Hi, I am Priya from Delhi, studying Design
```

Same result as before. The difference is purely in the syntax. `call()` takes individual arguments separated by commas. `apply()`takes a single array containing all the arguments.

A practical way to remember this: **c**all uses **c**ommas, **a**pply uses an **a**rray.

When would we actually use `apply()` over `call()`? When our arguments are already sitting in an array and we do not want to unpack them manually.

```javascript
let args = ["Mumbai", "Full Stack Development"];

student.greet.apply(anotherStudent, args);
// Hi, I am Priya from Mumbai, studying Full Stack Development
```

* * *

## bind()

`bind()` is a little different from `call()` and `apply()`. Instead of calling the function immediately, `bind()` returns a new function with `this` permanently set to whatever we specify. We can then call that new function whenever we want.

```javascript
let student = {
  name: "Gurjeet",
  introduce: function() {
    console.log("My name is " + this.name);
  }
};

let anotherStudent = { name: "Priya" };

let priyanIntroduce = student.introduce.bind(anotherStudent);

priyanIntroduce();
// My name is Priya
```

We used `bind()` to create a new function called `priyanIntroduce` where `this` is permanently set to `anotherStudent`. Now we can call `priyanIntroduce()` anywhere in our code and it will always use `anotherStudent` as the context.

This is useful when we want to pass a function around, store it for later use, or use it as a callback, but we need to make sure it always runs with the right `this`.

* * *

## call vs apply vs bind

All three let us control what `this` is inside a function. The difference is in how and when they execute:

`call()` runs the function immediately and accepts arguments one by one.

`apply()` runs the function immediately and accepts arguments as an array.

`bind()` does not run the function immediately. It returns a new function with `this` locked in, ready to be called later.

```javascript
let person = {
  name: "Gurjeet",
  sayHello: function(greeting, punctuation) {
    console.log(greeting + ", I am " + this.name + punctuation);
  }
};

let anotherPerson = { name: "Priya" };

// call — runs immediately, arguments one by one
person.sayHello.call(anotherPerson, "Hello", "!");
// Hello, I am Priya!

// apply — runs immediately, arguments as array
person.sayHello.apply(anotherPerson, ["Hey", "."]);
// Hey, I am Priya.

// bind — returns new function, call it later
let boundFn = person.sayHello.bind(anotherPerson, "Hi", "...");
boundFn();
// Hi, I am Priya...
```

* * *

## Why This Actually Matters

At first glance, `call()`, `apply()`, and `bind()` might feel like edge case tools. But they show up regularly in real JavaScript development. Borrowing methods between objects, setting the correct context for event handlers, working with callbacks, all of these situations involve controlling what `this` points to.

Understanding `this` and having these three tools in our toolkit means we are no longer guessing why a function is returning `undefined` for a property that clearly exists. We know exactly what `this` is, and we know how to change it when we need to.
