Function Borrowing Methods- call(), apply() and bind()

·

4 min read

Function borrowing as the name suggests, is the way for an object to borrow or use the functions defined by another object. Using call(), apply() and bind() built-in methods we can reuse the methods defined by another object without writing the same code.

With the help of these built-in methods we can just use the desired method from another object without inheriting all their properties and methods.

Before starting directly with these methods, lets discuss the tricky "this" keyword concept-

  • this keyword in a function references the execution context for that particular call
  • It makes functions reusable by letting you decide the context
  • The value of "this" keyword is determined entirely by how a function is called.

Implicit Binding

const person = {
  name: "Anjali",
  city: "Ghaziabad",
  printDetails: function (state, country) {
    console.log(this);
    console.log(this.name + " " + this.city + " " + state + " " + country);
  },
};

person.printDetails("Uttar Pradesh","India");

//Anjali Ghaziabad Uttar Pradesh India

This above example shows the Implicit Binding.Implicit binding means that the function is called by the object which owns it.

  • The rule of implicit binding is, when a function is invoked with the dot notation, the object to the left of that dot is what "this" keyword is referencing.
  • "this" keyword is referencing the "person" object in above example
  • this.name as person.name(Anjali)

Explicit Binding

Explicit binding of a function takes place when we use call(), apply() and bind() methods. We call these explicit because we are explicitly passing in a "this" context to these methods.

Let create person2 object, which wants to access the method "printDetails" of person object.

const person2 = {
  name: "John",
  city: "Bangalore",
};

person2.printDetails("Karnataka","India");

//Error - Uncaught TypeError: Cannot read properties of undefined (reading 'printDetails')

If we try to access it directly, we will encounter a typeError, because "person2" object doesn't own the printDetails() method, it is owned by person object. The way we can access or reuse the method defined by another object is by using call(), apply() and bind(). Lets cover them now.

call()

person.printDetails.call(person2,"Karnataka","India");

//output -> John Bangalore Karnataka India

Every function has a built in method name "call" which allows you to specify the context with which a function is invoked.

- The first argument(i.e, person2) passed to call is what "this" keyword inside "printDetails()" is referencing.
- If you want to specify the arguments to your function, we can pass then in after the first argument to call. There can be zero or n number of arguments which can be passed in a comma separated list. In the above example we have passed two arguments "Karnataka", "India" to call.

apply()

person.printDetails.apply(person2,["Karnataka","India"]);
//output -> John Bangalore Karnataka India

Every function has a built in method named "apply()" which allows you to specify the context with which a function is invoked.

  • The first argument passed to apply is what "this" keyword inside "printDetails()" is referencing.
  • "apply()" accepts an array as its second argument. If you notice above, we have passed state and country in an ["Karnataka","India"].

call() vs apply()

Now, you must be wondering if "apply" does the same thing as "call()", then what is the difference between them- call() takes in a comma separated arguments whereas latter takes in array of arguments.

bind()

let myDetails= person.printDetails.bind(person2,"Karnataka","India");
myDetails();
//output -> John Bangalore Karnataka India

bind() method works similar to call() method, but , instead of invoking the function, it return a new function that you can invoke whenever you wish to. In above example, we have first stored the new function in myDetails, and invoked later.

bind() method is similar to call() method, the only difference is that instead of calling the method, bind() method binds this printDetails() method with the object "person2" and returns the copy of that method, which can be invoked later.

Conclusion

  • call(), apply() and bind() helps us to reuse the method and in keeping the code clean and DRY.

  • These methods can help in achieving anonymous function binding, access "this" variable in callback and chaining constructor.

  • These built in methods exist on every JS function can be very useful.