const - JS | lectureA Closer Look At Functions

The Call & Apply Methods

A Closer Look At Functions

In this lecture, we're going to go back to the this keyword and learn how we can set the this keyword manually and also why we would want to do that.

Let's say we are an airline, and in this case, Emirates. Hence, let's create a very simple object for this airline with a very simple booking method.

script.js
const emirates = {
  airline: 'Emirates',
  iata: 'EK',
  bookings: [],
  book(flightNumber, passengerName) {
    console.log(
      `${passengerName} booked flight ${this.iata}${flightNumber} on ${this.airline}`
    );
    this.bookings.push({
      flight: `${this.iata}${flightNumber}`,
      passengerName,
    });
  },
};

Let's now try to book some flights.

script.js
emirates.book(123, 'John Doe');
emirates.book(456, 'Jane Doe');

Booking result

From the above output, we can see that everything works just as expected. What's important to understand here is that the this keyword points to the emirates object because that's the object on which the book method was called.

But now, let's say that after some years, the Emirates Group created a new airline called Emirates Executive.

script.js
const emiratesExecutive = {
  airline: 'Emirates Executive',
  iata: 'EE',
  bookings: [],
};

Emirates Executive, an entirely new airline, must be able to book flights just like the Emirates airline. How could we do that? Copying the same book method from the emirates object into the emiratesExecutive object is a bad practice.

Instead, we will take the method and store it in an external function. Making it possible for us to reuse that function for all of the different airlines. That is, we create a new book function and set tit to emirates.book.

script.js
/**
 * This is possible because JavaScript has First Class Functions!
 */
const book = emirates.book;

Now if we try to call this new book function, what do you think will happen?

script.js
book(123, 'Mike Smith');

Booking Error

We get an error. And I guess you already know why. But anyway, we get this error because our new book function is now a regular function call. And as we learned in one of the previous lectures, the this keyword points to undefined, at least in strict mode.

Now the question is, how do we fix this problem? Or, in other words, how de we tell JavaScript that we want to create a booking on the new Emirates Executive airline or Emirates airline? To fix this problem, since our new book function is a copy of emirates.book, we need to tell JavaScript explicitly what the this keyword should point to. That is, if we want to book an Emirates flight, the this keyword should point to emirates, but if we want to book an Emirates Executive flight, then the this keyword should point to emiratesExecutive.

To tell JavaScript what the this keyword should point to, there exist three methods: call, apply, and bind. When we first talked about the this keyword, I mentioned these three methods back then, and so now we are going to use them at least the call and apply methods.

Before showing you how to use the call method, always remember that a function is just an object, and objects have methods; therefore, functions can have methods, too, and the call method is one of them.

To use the call method, the first argument is the object on which the method should be called, followed by the list arguments that should be passed to the method.

script.js
book.call(emiratesExecutive, 789, 'Mike Smith');
console.log(emiratesExecutive);

Call Method

From the above output, you can see that we have our bookings array, which contains an object with flight number EE789 and passenger name 'Mike Smith', which belongs to emiratesExecutive.

Let's recap what happened here. This time, we did actually not call the book function ourselves. Instead, we called the call method and it's then this call method, which will call the book function with the this keyword set to emiratesExecutive or any other object we pass as first argument. Hence this allow us to manually and explicitly set the this keyword of any function that we want to call. Then all the arguments after the first one are simply the arguments of the original function.

Let's do the same thing with Emirates airline.

script.js
book.call(emirates, 509, 'Jake Turner');
console.log(emirates);

Call Method - 2

The string that we get from the output is correct, and in the Emirates bookings array we now have three bookings. That, of course, happened because this time, we set the this keyword inside of the function call to emirates.

Now that we have a way of manually manipulating the this keyword using the call method, we can now create more airlines into the Emirates Group like the Emirates SkyCargo.

script.js
const emiratesSkyCargo = {
  airline: 'Emirates SkyCargo',
  iata: 'ES',
  bookings: [],
};

book.call(emiratesSkyCargo, 963, 'Kevin Hill');

Call Method - 3

The second method as mentionned above is the apply method. The apply method does exactly the same thing. The only difference is that the apply method does not receive a list of arguments after the this keyword. Instead, it's going to take an array of arguments.

script.js
const flightBookingData = [738, 'Billy Bob'];
book.apply(emiratesSkyCargo, flightBookingData);

Apply Method

The apply method is no longer used that much in modern JavaScript because now, we have a better way of doing the same thing.

script.js
// This is equivalent to
book.apply(emiratesSkyCargo, flightBookingData);

//This
book.call(emiratesSkyCargo, ...flightBookingData);

To finish, with modern JavaScript, I always use the call method and then spread the arguments like above. In the next lecture we are going to learn about the bind method. It's more important than the call and apply methods, but does the same thing.