Javascript “this” Keyword and The Explicit Form Use Of The Terms Bind(), Call(), And Apply() methods
The use of the THIS keyword is tricky in JavaScript and is perplexing to both novice developers and those who have hands-on expertise in other programming languages.
So what does the word “this” mean in Javascript? Why is the use of “this” so confusing in JavaScript?
Well, in other programming languages, the usage of this keyword refers to the value or activity of the current class instance. whereas in JavaScript, the use or the value of “this” varies constantly based upon the function call.
The object to which this relates can vary implicitly depending on whether it is global, on an object, or in a constructor, and it can also vary explicitly depending on the use of the function methods, namely bind, call, and apply.
In JavaScript, the keyword “this” points out the object to which the function is attached. That is, in other words, the function call refers to the object it is attached to, not the function itself. So a function might have multiple objects to call and invoke the function.
And the value of this is determined by how the function is invoked, so unlike the scope concept where we consider the function declaration area, in this scenario we consider the function invocation area.
[Also Read, JavaScript Coding Interview Questions and Answers]
The 4 basic forms of “this” keyword that decide its value
The “this” keyword takes different shapes as a result of its function call. Here are the basic thumb rules for accessing the value of “this” through four different scenarios.
1. The use of the “this” keyword in Global Binding:
This refers to the global object in Default Binding or Global Binding. So basically, for standalone functions where the keyword “this” is used within the function, default binding is used.
The execution environment for execution is set to global by default, which implies that if code is run as part of a basic function call, the execution environment refers to a global object.
function myFunction(){
console.log('function');
console.log(this === window)
}
myFunction();
// Output:
// function
// true
console.log(this === window); // true
function myFunction(){
console.log(this)
}
myFunction();
// Output:
// Window {window: Window, self: Window, document: document, name: '', location: Location, …}
From the above example, we saw that the use of this keyword in standalone functions points to the window object, and the window object is the global object in the case of the browser. In a NodeJS context, the value of this will be a special object called global. But the use of the “this” keyword in “strict mode” results in an “undefined” output.
2. Method binding or implicit binding of “this” keyword
In JavaScript, a method is said to be a task that an object can execute or a function on an object. The method binding is quite simple to understand. If you see a dot notation for the function call, then understand that the function is invoked through a method. And the function refers to the object on the left side of the dot.
And when you use the dot notation to call a function in an object, implicit binding is used there for function invocation.
Let us look at the examples that briefly summarise the concept of the use of the “this” keyword by method binding.
function myFunction(){
console.log(this)
}
const obj1 = {
id: 1,
myFunction: myFunction
}
obj1.myFunction();
// Output:
// {id: 1, myFunction: ƒ}
In the above example, the function “myFunction” is invoked by the object “obj1”. So when the code is run, we get a result of the content connected with the object ‘obj1’. Since we already discussed that the output of this refers to the object which invoked the function, not the function itself, here, someKey: 1, myFunction: ƒ} is the output of the function myFunction.
The same concern can be constructed for nested objects and functions too.
function myFunction(){
console.log(`My name is ${this.name} and i am ${this.age} years old.`)
}
const obj1 = {
id: 1,
name: 'Praveen',
age: 28,
myFunction: myFunction,
nestedObject : {
id:1,
name: 'Naveen',
age: 29,
myFunction: myFunction
}
}
obj1.myFunction(); // My name is Praveen and i am 28 years old.
obj1.nestedObject.myFunction(); // My name is Naveen and i am 29 years old.
From the above example, when the myFunction is called by the nestedObject, this keyword is associated with only the nestedObject. So the outcome of obj1.nestedObject.myFunction() is this.age, which equals 29 and is nestedObject’s age property. And when the function is invoked by obj1, then this keyword is associated with only obj1. So the outcome of obj1.myFunction() is this.age, which equals 28 and is obj1’s age property.
So the simplest method to know which object is invoking the function is just by looking at the object that is left to the dot (.), which is implicitly bounded.
[Also Read, Prototype in JavaScript]
3. Use of the “this” keyword in the function Object()
An instance of the function or constructor is created when we use the keyword ‘new’ for function invoke. After the ECMAScript 2015 upgrade in JS, the class syntax was implemented for user-defined objects, but the basic function constructors were the traditional technique to initialise a user-defined object.
function Car(model, color){
this.model = model;
this.color = color;
this.getDetails = function(){
return this.model + ' car is '+ this.color
}
}
const car1 = new Car('BMW', 'Black');
console.log(car1.getDetails()) // BMW car is Black
4. Explicit binding of “this”
This can also be utilised through explicit binding, which allows you to choose and fix a specific object to be used by the function’s “this.”
Every function in JS has some built-in prototype functionality by default, and the few prominent methods for explicit binding of ‘this’ are call (), bind (), and apply ().
call()
The call method immediately executes the function after setting this inside it.
During the function call, the call() will pass the required object as the first parameter, and the user-defined parameters or arguments are passed later on.
Syntax: function.call(thisArg, arg1, agr2, …)
function greeting(){
console.log(`Hi, I am ${this.name} and i am ${this.age} years old`)
}
const person1 = {
name: 'Naveen',
age: 29
}
const person2 = {
name : 'Praveen',
age: 28
}
greeting.call(person1); // Hi, I am Naveen and i am 29 years old
greeting.call(person2); // Hi, I am Praveen and i am 28 years old
In the above example, the function ‘greeting’ of person1 and person2 are invoked separately by using the call() method where we pass the required objects as the thisArg’s in the method. Here in greeting.call(person1) function call, it prints the output of person1’s object. Similarly the same happened with person2 too.
The function arguments are also used in the call() method where the user-defined or function arguments are passed in the call method.
call() accepts a group of arguments separated by a comma succeeding with thisArg.
function greeting(greet){
console.log(`${greet}, I am ${this.name} and i am ${this.age} years old`)
}
const person1 = {
name: 'Naveen',
age: 29
}
const person2 = {
name : 'Praveen',
age: 28
}
greeting.call(person1, 'Hi'); // Hi, I am Naveen and i am 29 years old
greeting.call(person2, 'Hi Everyone'); // Hi Everyone, I am Praveen and i am 28 years old
From the above example, we can clearly understand how the function arguments/ user-defined arguments are set to the function using the call() method.
apply()
apply() is quite similar to the call(), the only difference you can notice is apply() takes the function arguments as an array.
Syntax: function.apply(thisArg, [argumentsArr])
function greeting(greet, lang){
console.log(`${greet}, I am ${this.name} and i am ${this.age} years old, i speak ${lang}`)
}
const person1 = {
name: 'Naveen',
age: 29
}
const person2 = {
name : 'Praveen',
age: 28
}
greeting.apply(person1, ['Hi', 'English']);
// Hi, I am Naveen and i am 29 years old, i speak English
greeting.apply(person2, ['Hi Everyone', 'Telugu']);
// Hi Everyone, I am Praveen and i am 28 years old, i speak Telugu
From the example we see that apply() is very advantageous for the functions where the need of a group of elements are required as function parameters.
bind()
bind() is the same but a bit different in design compared to call() and apply() methods. In bind(), it creates a new function for the fixed thisArg and the earlier function is invoked through the newly created function.
Syntax:
const newFunction = function.bind(thisArg, functionArguments);
newFunction();
function greeting(greet){
console.log(`${greet}, I am ${this.name} and i am ${this.age} years old`)
}
const person1 = {
name: 'Naveen',
age: 29
}
const person2 = {
name : 'Praveen',
age: 28
}
const person1Greet = greeting.bind(person1, 'Hi');
const person2Greet = greeting.bind(person2, 'Hi Everyone');
person1Greet(); // Hi, I am Naveen and i am 29 years old
person2Greet(); // Hi Everyone, I am Praveen and i am 28 years old
In the above example, the bind() method is used for function call for both person1 and person2 by creating a new function ‘person1Greet’ and ‘person2Greet’.
A quick summary of this, call(), bind(), apply()
- “this” refers to the object connected to the function call, not the function. In other programming languages, however, this keyword refers to the current class instance’s value or activity. In JavaScript, the purpose or value of “this” always switches depending on the function call.
- The object to which this refers can change implicitly based on whether it’s global, on an object, or in a function Object () [native code] (function constructor), as well as explicitly depending on how the function methods bind, call, and apply are used.
- The term “this” in JavaScript denotes the object to which the function is bound. That is, the function call refers to the object with which it is associated rather than the function itself. As a result, a function may be called and invoked by numerous objects—that is, a single parent function and multiple child objects may be invoked.
- In Default Binding or Global Binding, this refers to the global object. Default binding is utilised in standalone functions where the keyword “this” is used within the function.
- When you use the dot notation to call a function in an object, implicit binding is used. In such cases, this will refer to the object that was used to call the function. Simply, the object on the dot’s left side is the object that these refer to.
- When using explicit binding, we can invoke a function using an object even if the function is not in the object’s execution environment. Calling this, applying this, and binding this are three commonly used techniques for explicit binding of this.
- In the function call, call () makes use of thisArg as well as function arguments.
- apply () uses the thisArg and also function arguments in the function call, but the function parameters here are taken in the form of an array.
- Binding creates a new function for an already existing function and then takes the thisArg and function.