`this` in JavaScript

`this` in JavaScript

Introduction

One of the most discussed and confused topics among JavaScript developers. Let's understand this in JavaScript in-depth.

Before getting started with this, we need to understand a little about the JavaScript runtime environment and how JavaScript code is executed.

Execution Context

The environment (or scope) in which the line is being executed is known as the execution context. The JavaScript runtime maintains a stack of these execution contexts, the top execution context is the one currently being executed.

The object this refers to changes every time the execution context is changed.

Default case:

this refers to the global object (aka window object in browser)

By default, the execution context is global — it means if a code is being executed as part of a simple function call, then this refers to a global object.

Example:

function bar () {
    console.log("Let's understand this in JavaScript");
    console.log(this === window); 
}

bar();    //prints Let's understand this in JavaScript
console.log(this === window) //Prints true on console.

In strict mode, then the value of this will be marked as undefined. The global object refers to undefined in place of the windows object.

function baz () {
    'use strict';
    console.log("Let's understand this in JavaScript");
    console.log(this === window); 
}

baz()  // Strict mode enabled, prints false
          //prints Let's understand this in JavaScript

this points to a new instance

When a function is invoked with the new keyword, the function is known as a constructor function and returns an instance/object.

In such cases, the value of this refers to a newly created instance.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    this.printName = function() {
        console.log(`Your name is : ${this.firstName} ${this.lastName}`);
    }
}

const p1= new Person("Jane", "Dane"); // created an instance as new operator is used
p1.printName();  // Prints "Your name is : Jane Dane"

const p2 = new Person("John", "Doe"); 
p2.printName();  // Prints "Your name is : John Doe"

Since we used the new operator here, the function Person is now a constructor function and return a new instance.

this now points to a new instance of Person with properties firstName as Jane and lastName as Dane.

In case of p2.printName(), this points to a complete new instance of Person with properties firstName as John and lastname as Doe.

this with the fat-arrow function

In ES6, fat-arrow functions were introduced

this in fat-arrow points to the same object where it’s referring to outside of the function.

function add(num1, num2, callback) {
    callback(num1*num2);
}

const  person = {
    num1: 50,
    num2:20,
    makeAddtition: function() {
        add(this.num1, this.num2, function(sum) {
            console.log(sum);
            console.log(this === window);
        })
    }
}

person.makeAddtition();
//Prints 70
//Prints true

The callback function is invoked as a simple function call inside the add function, this here refers to the global object inside the execution context of the callback method.

this refers to an invoker object

In JavaScript, the property of an object can be a method or a simple value. When an object’s method is invoked, then this refers to the object which contains the method being invoked.


const  person = {
    username: "John",
    printName:function(){
         console.log(this.username)
    }
}

person.printName()  //Prints "John", this points to person object and username is set to John

const printName2 = person.printName 

printName2() //Prints "undefined", this now points global/window object and global object has no 
                        //username property

var username="Robert Paul"

printName3()  //Prints Robert Paul", this points to global object and global object has username 
                            //property

this with call, apply and bind

Every function in JavaScript has call, bind, and apply methods. These methods can be used to set a custom value to this in the execution context of the function.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    this.printName = function() {
        console.log(`Your name is : ${this.firstName} ${this.lastName}`);
    }
}

const person = new Person("John", "Doe");
person.printName(); // Prints "Your name is : John Doe"

const personTwo= new Person("Jane", "Dane")

person.printName.call(personTwo); // Here we are setting value of *this* to be personTwo object
                                   //Prints "Your name is : John Doe"

The difference between the call and apply methods is the way an argument is passed. In case of apply, the second argument is an array of arguments, whereas in the case of the call method, the arguments are passed individually.

Bind also works the same, the only difference is instead of calling the function, bind returns a new function that is associated with the passed context.

Summary

By default, this refers to the global object, window object in the case of a browser When a function is called using the call and apply methods, this refers to the value passed as the first argument of the call or apply method When a method is called as a property of an object, this refers to the object When a function is called with the new operator, this refers to the newly created instance

If you find this blog useful, do consider commenting/liking the post.