Call(), Apply() & Bind() functions in Javascript.

·

4 min read

Call(), Apply() & Bind() functions in Javascript.
  • These functions are usually used when we want to set the this keyword independent of how the function is being called in our code.

Lets understand this in a clear way with an example. Assume a flight company minimal object, it stores the

  • name of the flight
  • the iata code(location identifier code)
  • the bookings array and
  • has a method book that books the flight using the flight name and the name of the passenger as the arguments.
const airIndia = {
    airline: 'Air India',
    iataCode: 'AI3',
    bookings: [],
    book(flightNum, name) {
        console.log(`${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`);
        this.bookings.push({ flight: `${this.iataCode}${flightNum}`, name });
    }
}

Now, to book a flight we can simply call the book method and pass in the passenger name and the flightNumber.

airIndia.book(111, 'RahulK');
airIndia.book(112, 'devtuber');

// Output: 
// RahulK booked a seat on Air India flight AI3111
// devtuber booked a seat on Air India flight AI3112

Up until here, there was nothing to do with the call, apply and bind functions. But, now lets take it to the next step. Lets assume that AirIndia opens up a new subsidiary airline 'flyer'.

The object should have similar properties as to airIndia.

const flyer = {
    airline: 'Flyer',
    iataCode: 'FF3',
    bookings: [],
  book(flightNum, name) {
        console.log(`${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`);
        this.bookings.push({ flight: `${this.iataCode}${flightNum}`, name });
    }
}

// It will use the book method from the parent airline(AirIndia).

So, here we would exploit the DRY principle if we re-wrote the book() method within the flyer object. How can we improve this?

What happens when we try to use the book() from AirIndia object?

const bookTicket = airIndia.book;
bookTicket(24, 'Rahul'); // error
  • this will certainly give an error because when we store the book() method into the bookTicket, bookTicket no longer remains the method rather becomes the normal function whose this keyword points to undefined.

    Things to remember:

    • this always refers to an object.
    • this refers to an object which calls the function it contains.
    • In the global context this refers either to the window object or is undefined if the strict mode is on.

How to solve this?

  • One way is to create a book function explicitly that takes in three arguments: airline object, passenger name, flight number and books the flight for any airline.
  • Second way is to set the value of this using either the call(), apply() or bind() methods while calling book() from AirIndia.

Using Call(thisArg, ...parameters)

The call() method sets the 'this' inside the function and immediately executes that function.

  • Syntax: function.call(thisArg, param1, param2...)

So, now instead of passing only the parameters asked in the bookTicket(), we can also pass the object to which the this should reference to using the call().

const bookTicket = airIndia.book;
bookTicket.call(flyer, 24, 'Rahul');

// Output: Rahul booked a seat on Flyer flight FF224

Using Apply(thisArg, [param1, param2...])

Apply() method works similar to call(), it also sets the 'this' inside the function and immediately executes that function. Only difference is that it takes the arguments in the form of an array.

const bookTicket = airIndia.book;
bookTicket.apply(flyer, [24, 'Keyboard']);

// Output: Keyboard booked a seat on Flyer flight FF224

Using Bind(thisArg, optionalArguments)

Bind() actually works similar to call() and apply() but has some differences. The main difference is that bind() method creates a new function that, when called, has its this keyword set to the provided value.

const bookBind = airIndia.book.bind(flyer);
bookBind(24, 'Rahul');

// Output: Rahul booked a seat on Flyer flight FF224

Optionally, we can always provide the other arguments as well within the bind() method. We are allowed to pass in partial arguments too. Let make it clear through an example.

const bookBind = airIndia.book.bind(flyer, 25);
bookBind('Rahul');

// Output: Rahul booked a seat on Flyer flight FF225

In the above code, we have optionally passed the flight number and not the name within the bind() method, which is perfectly fine.

const bookBind = airIndia.book.bind(flyer, 25, 'Rahul');
bookBind();

// Output: Rahul booked a seat on Flyer flight FF225

In the above code, we have passed both the flight number and the name within the bind() method, which is perfectly fine too.