Call, Apply, and Bind Methods in JavaScript

Let’s take an object name that has two properties: firstName and lastName.

const name = {
  firstName: "John",
  lastName: "Snow",
};

This object should also have a method printFullName that prints the full name in the console. How do you write it?

Every object in JavaScript has access to the this keyword. In this method, this will point to the name object. Here, we can access this.firstName and this.lastName, which refer to the firstName and lastName properties of the name object.

const name = {
  firstName: "John",
  lastName: "Snow",
  printFullName: function () {
    console.log(this.firstName + " " + this.lastName);
  },
};

To invoke this method, we simply use name.printFullName().

const name = {
  firstName: "John",
  lastName: "Snow",
  printFullName: function () {
    console.log(this.firstName + " " + this.lastName);
  },
};

name.printFullName();

You will see the full name printed in the console.

Now, suppose we have another object, name2, which also has firstName and lastName properties:

const name2 = {
  firstName: "Tyrion",
  lastName: "Lannister",
};

If we want to print this name, one option is to copy the printFullName method from the name object to name2. However, that's not a good approach.

This is where the call method comes in.

call

Using the call method, we can do something called function borrowing. This allows us to borrow methods from one object and use them with the data of another object.

Let’s see how we can do that.

First, take the function that needs to be called:

name.printFullName;

Every function in JavaScript has access to the special call method. The first argument of call is the reference or, in simple terms, what we want this to point to. In this case, we want this to point to name2. So we pass name2 as the first argument.

name.printFullName.call(name2);

This will print "Tyrion Lannister". It's a very useful technique that allows us to borrow methods from other objects.

In general, we don’t store the function we want to borrow inside an object. Instead, we define it separately.

const name = {
  firstName: "John",
  lastName: "Snow",
};

const name2 = {
  firstName: "Tyrion",
  lastName: "Lannister",
};

const printFullName = function () {
  console.log(this.firstName + " " + this.lastName);
};

printFullName.call(name);
printFullName.call(name2);

Depending on our needs, we can pass different references.

Using call with Additional Parameters

What if we had more parameters inside printFullName? For example, a greeting parameter?

const printFullName = function (greeting) {
  console.log(greeting + " " + this.firstName + " " + this.lastName);
};

In this case, the first parameter in call will always be the reference, and the following parameters will be the arguments to the function. Since we have a greeting argument, we can pass it as the second argument.

const name = {
  firstName: "John",
  lastName: "Snow",
};

const name2 = {
  firstName: "Tyrion",
  lastName: "Lannister",
};

const printFullName = function (greeting) {
  console.log(greeting + " " + this.firstName + " " + this.lastName);
};

printFullName.call(name, "Hello");
printFullName.call(name2, "Hi");

This will print:

  • "Hello John Snow"
  • "Hi Tyrion Lannister"

Now let’s talk about the apply method.

apply

The only difference between the call and apply methods is how we pass arguments.

Here’s how it works:

The first argument to apply is the reference to the this context, and the second argument is an array of arguments that we want to pass to the function.

const name = {
  firstName: "John",
  lastName: "Snow",
};

const name2 = {
  firstName: "Tyrion",
  lastName: "Lannister",
};

const printFullName = function (greeting) {
  console.log(greeting + " " + this.firstName + " " + this.lastName);
};

printFullName.apply(name, ["Hello"]);
printFullName.apply(name2, ["Hi"]);

So instead of passing arguments individually, as with call, with apply we pass these arguments as an array. That’s it.

Now let’s move on to the bind method.

bind

The bind method is similar to call and apply, but instead of immediately calling the method, it binds the method to the object and returns a new function.

Here’s how it works:

const printMyName = printFullName.bind(name, "Hello");

This creates a new function, printMyName, that is bound to the name object. It doesn’t call the method directly like call and apply do. Instead, it returns a function that can be invoked later.

You can then invoke this function like a normal function:

const printMyName = printFullName.bind(name, "Hello");

printMyName();

So essentially, bind is used to create and store a copy of the method that can be invoked later. The main difference between call and bind is that bind gives you a new function that can be called later, whereas call and apply execute the function immediately.

Get my free, weekly JavaScript tutorials

Want to improve your JavaScript fluency?

Every week, I send a new full-length JavaScript article to thousands of developers. Learn about asynchronous programming, closures, and best practices — as well as general tips for software engineers.

Join today, and level up your JavaScript every Sunday!

Thank you, Taha, for your amazing newsletter. I’m really benefiting from the valuable insights and tips you share.

- Remi Egwuda