The this
keyword in Javascript is an essential concept, and many developers sometimes find it hard to understand. The value this
can depend on many factors. And what makes it more confusing is that its value is determined at the runtime.
In this section, we will go through the concept of this
keyword in-depth and try to make sense of how it works in Javascript.
Global scope
Before we get into the complexity of the this
keyword, let’s first see what it returns when used in a global scope. For this, we will simply log the this
value using console.log
.
console.log(this);
Output:
Window {}
var x = 10;
console.log(this); // Window{}
console.log(this.x); // 10
As you can see this
returns the global object Window
when used in the global scope.
Calling “this” from a function
The this
keyword inside a function refers to the global object. To illustrate this, we look at some examples.
We will begin by creating a simple function and logging this
value.
function greet() {
console.log(this);
};
greet();
Output:
Window{}
Here, we have a function by the name greet()
which prints the this
keyword. The value of this
in this case is the global object Window
.
Now let’s create two variables by the same name, one inside greet()
function and another in the global scope.
var message = "Hello from Global";
function greet() {
var message = "Hello from inside greet";
console.log(this.message);
};
greet();
Output:
Hello from Global
At first glance, you might think that this.message
will contain the string from the message
variable inside of the function greet()
.
But from the previous example, we have seen the this
inside the function returns global object Window
. Hence, the global variable message
containing text Hello from Global
gets printed.
strict mode - the value of “this” is undefined
In the strict mode, it is important to note that the value of this
does not bind to the global object Window
and its value is undefined
.
So, if we try to run the above code in strict mode. It will throw an error.
use strict;
function greet() {
console.log(this);
};
greet();
Output:
Uncaught SyntaxError: Unexpected identifier
Calling “this” from an object method
Let us see how this
behaves when called from inside an object’s method. To do this we will first create an object with a method.
var actor = {
name: "Mickey",
genre: "comedy",
bio: function() {
console.log(this);
}
};
actor.bio();
Output:
{name: 'Mickey', genre: 'comedy', bio: ƒ}
In this case, the object actor
invokes the method bio()
. Hence, this
refers to the object actor
and not the global object Window
.
Let us take another example,
var employee1 = {
name: "Mickey",
bio: function() {
console.log(this);
}
}
var employee2 = {
name: "Donald",
bio: employee1.bio
}
employee1.bio(); //{name: 'Mickey', bio: ƒ}
employee2.bio(); // {name: 'Donald', bio: ƒ}
Here, we have created two objects, employee1
and employee2
. The employee1
object contains a method called bio()
which prints the this
value.
The output of employee1.bio()
is simple, this
refers to object employee1
.
In the case of employee2
, it’s property bio
calls the method of employee1
i.e, employee1.bio
. But remember, the invoking object is still employee2
(employee2.bio();). Hence, this
refers to employee2
in this case.
call() and apply()
Both call
and apply
methods are used to invoke functions. Both the methods take value of this
as the first argument followed by one or more arguments for the function.
Syntax:
call(this, arg1, arg2…)
apply(this, [arg1, arg2, …])
As you can notice, the difference between the two methods is that the second argument is array-like
in apply()
method.
We will look at some examples to see how this
values behaves when using both the methods.
Let’s suppose we have two objects player1
and player2
. And we also have a function named getFullName
that will simply log this
value.
var player1 = {
fName: "Mickey",
lName: "Mouse"
};
var player2 = {
fName: "Donald",
lName: "Duck"
};
function getFullName() {
console.log(this);
};
Since we know the first argument in both the methods takes the this
argument, the getFullName
function when invoked using call()
or apply()
should display the this
object as per the first argument specified.
Output:
getFullName.call() // Window {}
getFullName.call(player1); // {fName: 'Mickey', lName: 'Mouse'}
getFullName.apply(player1); // {fName: 'Mickey', lName: 'Mouse'}
getFullName.call(player2); // {fName: 'Donald', lName: 'Duck'}
getFullName.apply(player2); // {fName: 'Donald', lName: 'Duck'}
bind() function
The bind()
function is similar to the call
and apply
function. However, when you call bind
, it creates a new function. The value this
is set to the value passed as the first argument to the bind
function. You can also pass one or more arguments that can be used by the function.
Syntax:
bind(this, arg1, arg2 …)
Let us look at an example,
var player1 = {
fName: "Mickey",
lName: "Mouse"
};
var player2 = {
fName: "Donald",
lName: "Duck"
};
function getFullName() {
console.log(this);
};
//Global object
var global = getFullName.bind();
global(); // Window {window: Window, self: Window, document: document ...}
var p1 = getFullName.bind(player1);
p1(); // {fName: 'Mickey', lName: 'Mouse'}
var p2 = getFullName.bind(player2);
p2(); // {fName: 'Donald', lName: 'Duck'}
Here, we have a function getFullName
that logs the this
value. When you call it without any arguments, it will return this
as a global object i.e, Window {}
.
As we know that bind
creates a new function, to invoke our function we will have to call the var global
as a function using the parentheses (global()
).
Next, we have called the bind
function with player1
as the first argument. Hence, the value of this
is player1
. Similarly, when you call the bind method with player2
as the first argument, this
returns player2
.
“this” when using constructors
Constructor is a function that is called using the new keyword. To call a function as a constructor, we have to use the new
keyword along with the function name.
function Greet(){
console.log(this);
}
Greet(); //Window {}
var msg = new Greet(); // Greet {}
Here, we have a Greet function that simply logs this value. When we call the Greet()
without the new
constructor, the function returns Window
global object.
To call this function as a constructor, we can use to new keyword along with the function name. The this
now returns Greet{} object in this case.
Notice, that the first letter of the function name is in uppercase. This is to indicate that the function Greet is going to be invoked as a constructor later in the code.