Skip to main content

Command Palette

Search for a command to run...

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

Updated
4 min read
The Magic of this, call(), apply(), and bind() in JavaScript

Tell me one thing, have you ever faced confusion about this in JavaScript? Ever outputs of this seemed to be unpredictable to you? If yes, then reading this blog will clear you a lot.

In this blog I will try to make you understand this, call(), bind(), apply() in such a way which helped me to clear my confusion.

Let's first define what this actually means:

What does this mean in JavaScript?

Simplest way to remember is:

this refers to the object that is calling the function.

Instead of thinking of it as a variable, think of it as a reference to the caller of the function. If we try to understand who calls the function it itself tells us what this will be.


this inside a normal function

function show() {
  console.log(this);
}

show();

If you run this in a browser, the output will usually be the global object (window).

Why does this happen?

Because the function is called directly, not through any object. In this situation, JavaScript treats the global object as the caller. So here, this refers to the global object.


this inside an object

const person = {
  name: "John",
  greet: function () {
    console.log("Hello " + this.name);
  }
};

console.log(person.greet()); //Hello John

Here the function is called like this: person.greet()

So the object person is calling the function. Because of that, this refers to person.That is why this.name becomes "John".


Method Borrowing Problem

Suppose we have another object that doesn’t have the greet method.

const person1 = {
  name: "John",
  greet: function () {
    console.log("Hello " + this.name);
  }
};

const person2 = {
  name: "Alice"
};

Now we want person2 to use the greet method from person1. Instead of rewriting the function, JavaScript allows us to borrow the method. This is where call() becomes useful.


What does call() do?

The call() method allows us to call a function with a specific object as this.

person1.greet.call(person2); //Hello Alice

Here we are calling the greet function, but telling JavaScript that this should refer to person2. So even though the method belongs to person1, it runs using the data from person2. This technique is often called method borrowing.


What does apply() do?

The apply() method works almost the same as call().

The main difference is how arguments are passed to the function.

function introduce(age, city) {
  console.log(this.name + " is " + age + " years old and lives in " + city);
}

const person = {
  name: "John"
};

console.log(introduce.apply(person, [25, "London"]));
//John is 25 years old and lives in London

The key thing to notice here is that the arguments are passed as an array.

So the difference only is:

  • call() → We pass arguments individually.

  • apply() → We pass arguments as an array.


What does bind() do?

Unlike call() and apply(), the bind() method does not execute the function immediately. Rather, it returns a new function where this is permanently set.

function greet() {
  console.log("Hello " + this.name);
}

const person = {
  name: "John"
};

const greetJohn = greet.bind(person);

console.log(greetJohn()); // Hello John

Here bind() creates a new function where this always refers to person. The function runs later, but the value of this remains fixed.


Difference Between call, apply, and bind

So in simple terms:

  • call() → run the function immediately with a specific this

  • apply() → same as call but arguments are in an array

  • bind() → create a new function with fixed this


A common situation where this gets lost

Sometimes when we store a method in another variable, the connection with the object is lost.

Example:

const person = {
  name: "John",
  greet() {
    console.log("Hello " + this.name);
  }
};

const greetFunc = person.greet;// its not the function call, its reference of the function

console.log(greetFunc()); //Hello undefined

Why? Because now the function is not called by person anymore.

We can fix this using bind().

const greetFunc = person.greet.bind(person);
greetFunc();

Now this will always refer to person.