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.