Hello Sunil
javascript–this-keyword-feature-image

Simplifying JavaScript – this  Keyword

Hey everyone! In this article we are going to talk about THIS keyword in JavaScript.

This used to be a concept that confused everyone a little bit, so we will try to break it down for you so you can understand its uses and in what situations can it be useful. Let’s go!

What’s the THIS keyword?

When we use ‘this’ in our daily conversations it always has a context attached with it, right? For instance, the sentence “This is my house” can only make sense in two ways when you are inside the house or you point to the house you are talking about.

If in the middle of the street you say “This is my house” it doesn’t really make sense, because ‘this’ isn’t really pointing to anything.

If you have a picture of your house then regardless of the location you can point to the picture and attach the context to ‘this’, it will be like ‘this house(in the picture) is my house’.

Similarly in JavaScript, this keyword will point to something according to the context it is in or we can point it to the thing we want using call, apply and bind .

Also Read: Understanding – Call, Apply, Bind

This will make better sense when we see the different contexts this can be defined in.

Global Context

When we create a JavaScript file, even if there are zero lines of code written in the file a few things are created. One of the things created is the window object.

The window object contains different properties and methods including things related to DOM.

So when this is used alone in global context, this refers to the global object (window object in browsers).

For example,

let a = this;
console.log(a);  // Window {}

this.name = 'Sunil';
console.log(window.name); // Sunil

Here, this.name is the same as window.name.

Function Context

From here onwards, things will get a little weird, so stick with us.

In JavaScript, we can call a function in the following ways:

  • Function invocation
  • Method invocation
  • Constructor invocation
  • Indirect invocation

Each function invocation defines its own context. Therefore, the this behaves differently.

1) Simple Function Invocation

When this is used in a function (non-strict mode), this refers to the global object (window object in browsers).

For example,

function greet() {

    // this inside function
    // this refers to the global object
    console.log(this);
}

greet(); // Window {}

Let’s take one more example:

function show() {
   console.log(this === window); // true
}

show();

When you call the show() function, the this references the global object, which is the window on the web browser.

Calling the show() function is the same as:

window.show();

Function with Strict Mode

When this is used in a function with strict mode, this is undefined.

For example,

"use strict";

function show() {
    console.log(this === undefined); //true
}

show();

2) Method Invocation

When we call a method of an object, JavaScript sets this to the object that owns the method. 

Whenever we are calling functions inside object, it is known as method.

For example:

const person = {
    name : 'Sunil',
    age: 25,

    // this inside method
    // this refers to the object itself
    greet() {
        console.log(this);
        console.log(this.name);
    }
}

person.greet();

//{name: "Sunil", age: 25, greet: ƒ}
//Sunil

In the above example, this refers to the person object.

When we access this inside an inner function (inside a method), this refers to the global object.

For example,

const person = {
    name : 'Sunil',
    age: 25,

    // this inside method
    // this refers to the object itself
    greet() {
        console.log(this);        // {name: "Sunil", age ...}
        console.log(this.age);  // 25

        // inner function
        function innerFunc() {
        
            // this refers to the global object
            console.log(this);       // Window { ... }
            console.log(this.age);    // undefined
            
        }

        innerFunc();

    }
}

person.greet();
//{name: "Sunil", age: 25, greet: ƒ}
//25
//Window { …}
//undefined

Here, this inside innerFunc() refers to the global object because innerFunc() is inside a method.

However, this.age outside innerFunc() refers to the person object.

3) Constructor Invocation

When a function is invoked with the new keyword, then the function is known as a constructor function and returns a new instance. In such cases, the value of this refers to a newly created instance.

For example:

function Person(fn, ln) {
	this.first_name = fn;
	this.last_name = ln;

	this.displayName = function() {
		console.log(`Name: ${this.first_name} ${this.last_name}`);
	}
}

let person = new Person("Sunil", "Pradhan");
person.displayName();  // Prints Name: Sunil Pradhan
let person2 = new Person("Ram", "Sharma");
person2.displayName();  // Prints Name: Ram Sharma

In the case of person.displayName()this refers to a new instance person, and in case of person2.displayName()this refers to person2 (which is a different instance than Person).

4) Indirect Invocation

In JavaScript, all functions are objects. They are the instances of the Function type. Because functions are objects, they have properties and methods like other objects.

To complicate the subject a little more, JavaScript provides three native methods that can be used to manipulate the way the this keyword behaves.

These methods are call, apply and bind. Let’s see how they work.

let honda = {
    brand: 'Honda'
};
let audi = {
    brand: 'Audi'
};

function getBrand(prefix) {
    console.log(prefix + this.brand);
}

getBrand.call(honda, "It's a "); //It's a Honda
getBrand.call(audi, "It's an "); //It's an Audi

In this example, we called the getBrand() function indirectly using the call() method of the getBrand function.

We passed honda and audi object as the first argument of the call() method, therefore, we got the corresponding brand in each call.

The apply() method is similar to the call() method except that its second argument is an array of arguments.

let honda = {
    brand: 'Honda'
};
let audi = {
    brand: 'Audi'
};

function getBrand(prefix) {
    console.log(prefix + this.brand);
}

getBrand.apply(honda, ["It's a "]); // "It's a Honda"
getBrand.apply(audi, ["It's an "]); // "It's a Audi"

Lets see an example of bind:

When we call a method of an object, JavaScript sets this to the object that owns the method.

let car = {
    brand: 'Honda',
    getBrand: function () {
        return this.brand;
    }
}

console.log(car.getBrand()); // Honda

In this example, this object in the getBrand() method references the car object.

Since a method is a property of an object which is a value, we can store it in a variable.

let brand = car.getBrand;

And then call the method via the variable.

let car = {
    brand: 'Honda',
    getBrand: function () {
        return this.brand;
    }
}

let brand = car.getBrand;
console.log(brand()); // undefined

We get undefined instead of "Honda" because when we call a method without specifying its object, JavaScript sets this to the global object in non-strict mode and undefined in the strict mode.

Also Read: Understanding – Call, Apply, Bind

To fix this issue, we can use the bind() method. The bind() method creates a new function whose this keyword is set to a specified value.

let car = {
    brand: 'Honda',
    getBrand: function () {
        return this.brand;
    }
}

let brand = car.getBrand.bind(car);
console.log(brand()); // Honda

JavaScript This In Arrow Functions

Arrow functions don’t have own version of this. They will always inherit from the parent.

const greet = () => {
    console.log(this);
}
greet(); // Window {...}

What can we expect this to log? same as with normal functions, window or global object.

Arrow functions don’t have their own ‘this’ keyword so they inherit the value of ‘this’ keyword from their direct parent when it is called.

Same result but with different reason. With normal functions the scope is bound to global object by default, arrows functions, as we said before, do not have their own this but they inherit it from the parent scope, in this case the global one.

What would happen if we add “use strict”?

const greet = () => {
  'use strict';
    console.log(this);
}
greet(); // Window {...}

Nothing, it will log the same result, since the scope comes from the parent one.

Let’s take one more example:

const greet = {
    name: 'Sunil',

    // method
    sayHi () {
        let hi = () => console.log(this.name);
        hi();
    }
}

greet.sayHi(); // Sunil

Here, this.name inside the hi() function refers to the greet object.

JavaScript This In Event Listeners

Here this keyword points to the element on which the event is handled or listened. Let’s understand by code snippet.

<body>
	<p>I hope you all are doing well.</p>
	<script>
		const text = document.querySelector('p');

		text.addEventListener('click', function () {
			console.log(this);
			//<p>I hope you all are doing well.</p>
		})
	</script>
</body>

JavaScript This In Class Methods

It is similar to constructor invocation i.e. within a class this point to the current instance of the class.

class Theatre {
			constructor(person, movie) {
				this.person = person
				this.movie = movie
			}
			display() {
				console.log(`${this.person} is watching ${this.movie}`)
			}
		}

		const sunil = new Theatre("Sunil", "Lagaan")
		const anil = new Theatre("Anil", "Fanaa")

		sunil.display()
		//output : Sunil is watching Lagaan
		anil.display()
		//output : Anil is watching Fanaa

Here the instances being sunil and anil.

Conclusion

Thanks for reading this post. Hope, this post will make you understand how this works in JavaScript 😎.

To summarize,

🤔 ‘This’ in JavaScript

JavaScript this keyword refers to the object it belongs to.

It has different values depending on where it is used:

1) Alone and independent, this refers to the global object (window).
2) In a regular function, this referes to the global object.
3) In a function with ‘strict’ mode, this refers to undefined.
4) In a method, this refers to its parent object.
5) Arrow functions will always inherit from the parent.
6) In an event, this refers to the element that received the event
7) When the “new” keyword is used, this will refer to the new object.
8) Within a class this point to the current instance of the class.
9) Call, bind, and apply can be used to set this value.

Three methods to bind this keyword explicitly

  • call(): It is used when one value or no arguments are to be passed to the function. call(object, argument-1,...,argument-n)
  • apply(): It is used when multiple value arguments are passed to the function. It allows us to pass array as a argument. apply(object, array)
  • bind(): It is similar to call(), only difference is it returns a brand new function, which can be invoked later.

Comments “this” if you got any doubt or suggestions? Let’s meet on next post with another JavaScript concept.

Have a beautiful day 🙂.

Resources

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Similar articles you may like

Sunil Pradhan

Hi there 👋 I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.

Add comment

Stay Updated

Want to be notified when our article is published? Enter your email address below to be the first to know.

Sunil Pradhan

Hi there 👋 I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.