Call, Apply and Bind In JavaScript

In JavaScipt, as we know, an object has its own properties and methods. Let us take a quick look.
  1. function A(firstName,lastName){  
  2.     this.firstName = firstName;  
  3.     this.lastName = lastName;  
  4.     //I am using Template literals (Introduce in ES 6) ${this.firstName} to show the details  
  5.     this.getUserDetails = function(city,state){  
  6.         var details = `User's name is ${this.firstName} ${this.lastName} and address is ${city} ${state}`  
  7.         return details;  
  8.     }  
  9. }  
  10.   
  11. function B(firstName,lastName){  
  12.     this.firstName = firstName;  
  13.     this.lastName = lastName;  
  14.     //I am using Template literals (Introduce in ES 6) ${this.firstName} to show the details  
  15.     this.getUserDetails = function(city,state){  
  16.         var details = `User's name is ${this.firstName} ${this.lastName} and address is ${city} ${state}`  
  17.         return details;  
  18.     }  
  19. }  
  20.   
  21. //Create objects  
  22. var a = new A("Vipin","Sharma");  
  23. var b = new B("Ashish","Sharma");  
  24.   
  25. console.log(a.getUserDetails("Jhansi","UP"));  
  26. console.log(b.getUserDetails("Mathura","UP"));  
Output 
 
User's name is Vipin Sharma and address is Jhansi UP
 
User's name is Ashish Sharma and address is Mathura UP 
 
As we can see, there are two identical methods for both objects but we are using both the methods to get the user's details. We need to avoid code repetition.
 
Let's take a look at how to use Call, Apply, and Bind.
 
In the below code, I have created two function constructors and one method. I have also created objects for both function constructors.
  1. function A(firstName,lastName){  
  2.     this.firstName = firstName;  
  3.     this.lastName = lastName;  
  4. }  
  5.   
  6. function B(firstName,lastName){  
  7.     this.firstName = firstName;  
  8.     this.lastName = lastName;  
  9. }  
  10.   
  11. //create a single function to get user's details
  12. var getUserDetails = function(city,state){  
  13.     var details = `User's name is ${this.firstName} ${this.lastName} and address is ${city} ${state}`  
  14.     return details;  
  15. }  
  16.   
  17. //Create objects  
  18. var a = new A("Vipin","Sharma");  
  19. var b = new B("Ashish","Sharma");  
call() method
 
Syntax
 
functionName.call(objectName,functionArguments)
  1. //a and b are objects for A and B function constructor.  
  2. //Jhansi and UP are parameters passed into the function.  
  3. console.log(getUserDetails.call(a,"Jhansi","UP"))  
  4. console.log(getUserDetails.call(b,"Mathura","UP"))  
Output
 
User's name is Vipin Sharma and address is Jhansi UP
 
User's name is Ashish Sharma and address is Mathura UP
 
As you can see, there are no parentheses after the function name because it is accessed as an object. We are using a single method (getUserDetails) for both objects. 
 
apply() method
 
Syntax
 
functionName.apply(objectName,[functionArguments])
 
The apply() method works exactly the same as call() works except it accepts only two parameters,
  1. Object
  2. An array of parameters that should be passed into the function. 
  1. //array of parameters that will pass to the function.  
  2. var arr = ["Jhansi","UP"];  
  3. var arr1 = ["Mathura","UP"];  
  4.   
  5. //arr array for object a call  
  6. console.log(getUserDetails.apply(a,arr))  
  7.   
  8. //arr1 array for object b call  
  9. console.log(getUserDetails.apply(b,arr1))   
Output
 
User's name is Vipin Sharma and address is Jhansi UP
 
User's name is Ashish Sharma and address is Mathura UP
 
bind() method
 
bind() is little bit different from call() and apply().
 
Let's take a look with example 
  1. //passing parameters to bind()    
  2. console.log(getUserDetails.bind(a,"Jhansi","UP"))    
 If I run the above code, I will get a function object back, not the correct result.
 
Output
 
function (city,state){
var details = `User's name is ${this.firstName} ${this.lastName} and address is ${city} ${state}`
return details;
}
 
Instead of giving me the result, it is giving me a function object so we can do it like below - 
  1. //Storing function object to a variable.  
  2. var obj = getUserDetails.bind(a);  
  3. //calling function object with parameters.  
  4. console.log(obj("Jhansi","UP"));  
Or, another way,
  1. //we can directly pass the parameters to function objets  
  2. console.log(getUserDetails.bind(a)("Jhansi","UP"));    
Output
 
User's name is Vipin Sharma and address is Jhansi UP 
 
this Keyword
 
Let's change the code a little bit. Instead of passing the object name, I am passing "this".
  1.  
  2. var getUserDetails = function(city,state){    
  3.     var details = `User's name is ${this.firstName} ${this.lastName} and address is ${city} ${state}`    
  4.     return details;    
  5. }    
  6. //this is referring to global object
  7. console.log(getUserDetails.bind(this)("Jhansi","UP"));    
Output
 
User's name is undefined and address is Jhansi UP 
 
As you can see in the ouput, it is giving undefined for firstname and lastname. When we specify this in global namespace, then this belongs to the global object but we haven't defined firstname and lastname in global namespace.
  1. //Parameters - City and State  
  2. var getUserDetails = function(city,state){    
  3.     var details = `User's name is ${this.firstName} ${this.lastName} and address is ${city} ${state}`    
  4.     return details;    
  5. }    
  6.   
  7. //now firstname and lastname are belong to global object  
  8. var firstName = "Vipin";  
  9. var lastName = "Sharma";  
  10.   
  11. //this is referring to global object  
  12. console.log(getUserDetails.bind(this)("Jhansi","UP"));    
Output
 
User's name is Vipin Sharma and address is Jhansi UP