DEV Community

loading...
Cover image for Master ‘this’ in JavaScript

Master ‘this’ in JavaScript

polymathsomnath profile image Somnath Singh Originally published at javascript.plainenglish.io ・7 min read

In this article, we cover the all-important yet so confusing topic in JavaScript which is the “this” keyword.

TL;DR

If “this” scares you, do not worry! We will learn how to determine the value of the “this” keyword using five simple rules.

Those five simple rules are as follows:

  • The Regular One — Default binding
  • Function Inside an ObjectImplicit binding
  • Function BorrowingExplicit binding
  • Using Function to Create ObjectsNew binding
  • How Arrow Function Differs from the Regular Ones— Lexical binding

Don’t worry about these scary names. Computer Science people have a fancy for naming terms so that they sound extra-terrestrial. Under the hood, they are just common concepts that any willing human can understand.

The “this” variable corresponds to how you invoke a function. These rules help us to determine the value of this in various scenarios.

Once you understand these rules, then you would not fear them anymore.

Before we begin, please go through this article to understand how this works.

What is “this” in brief

In JavaScript, whenever a function is called, a new execution context is created by the JavaScript engine. That execution context exists until the function has finished executing. Every execution context contains a variable called ‘this’.

#Rule 1. Default binding

When calling a function in a standard way shown above, “this” will actually refer to the global object!

In the browser, the global object means the Window object.

One exception to remember — that is when strict mode is enabled. By writing “use-strict” you can prevent anything from being declared on the global object.

#Rule 2. Implicit binding

If the function is contained within an object, then that object will be referenced by “this”.

For the above, the this keyword will point to the personObj

#Rule 3. Explicit binding

We saw how this points to the global object and in another case, it points to the object which contains it. Wouldn’t it be nice to able to control what this variable ends up being when the function is called?

Words like call, apply, and bind usually causes terror in new developers. In reality, they are all functions that can be used to explicitly set the value of “this”.

Let us understand it with an example.

Suppose we have two objects, let us say personObj and readerObj

Both the object has a name property. The personObj has a function that can print the value inside the name but, the readerObj does not have any such feature!

Here we can make use of one of the three methods — call, apply or bind.

This process is called function borrowing.

We borrowed the sayName method for the readerObj.

Now we can print the name property that is in readerObj

We are calling the sayName method from personObj, but at the same time, we are instructing the JavaScript engine that the ‘this’ variable in the sayName method should point to readerObj.

So when the JavaScript engine executes the code, the this variable in the sayName function does not point to the personObj but it points to the readerObj.

Does that make sense?

Not just that — we can also pass some arguments when we use the call function.

We passed Namaste as an argument

We can make use of the argument in the sayName method.

When we execute the code, we will get the output along with the passed argument.

The apply method works the same way, but instead of regular arguments, it takes an array as an argument.

The bind method also works the same way — it can accept a regular argument.

But unlike call and apply — bind returns a function — that function can be stored in a variable and can be executed in the future.

One can see the use of bind in function currying — a topic that we will cover in the future.

#Rule 4. New binding

We use the new keyword to create an instance or copy of an object. What the new keyword does is:

  • It creates an empty object and then instructs the keyword this to point to that empty object.
  • It then adds a return this statement to the end of that function.

Remember, when an instance of an object gets created using the new keyword, “this” always points to that newly created instance.

Let us understand this with an example.

When we run this code, what are we supposed to get?

As we said — an empty object!

What is happening under the hood is

What? Are we invoking the function?

Yes!

See, I told you it is getting invoked.

Let us look at the whole thing.

If we put some value in the function, it will put that in the newly created object and then return it!

When we console.log(newPersonObj)

Let us finish this concept with an animation.

Since dev.to supports animation of 500 frames only, I am attaching an external link to the animation
Go here for the animation

In the above example, we are using a function to create an object.

This type of function is known as a function constructor.

Remember, in the newPersonObj, which stores the copy of personObj— the “this" variable points to empty personObj

Does it make sense now?

Good! Let us now understand the last rule.

#Rule 5. Lexical binding

With the advent of ES6 — we got arrow functions. Arrow functions with their ultra-lean syntax are a natural replacement for their traditional anonymous counterparts.

To explicitly invoke an arrow function, as with a regular anonymous function, you would assign it to a variable first:

Arrow functions are just like regular anonymous functions, with one major exception- the behavior of this object inside the function.

In a regular function, the value of "this" is context-based- call the function inside a link, and "this" points to the link's object; call it inside one more function like setInterval(), then "this" points to the global window object.

For example, the following example attempts to call the start() method of a custom object to increment its counter property by 1 every second, though it fails due to an incorrect assumption of the "this" object reference counter.

In the above, this.counter fails to properly reference the counter property of the countup object, though the error may not be so obvious to spot. One can either mistakenly or carelessly assume that "this" points to the countup object, when in fact it points to the global window object due to the context "this" is being called- inside the global window method setInterval().

The result is a reference to a non-existent window.counter property that will repeatedly return NaN when we try to increment it. To properly reference the countup object then inside the anonymous function, we should cache a reference to the correct "this" object before the context changes to a different one:

The "this" object inside an arrow function is lexically bound, which is just a fancy way of saying its value is static and determined by the place where the “this" keyword is defined.

Contrast that with regular functions, where "this" is dynamic and based on the context it's called regardless of the scope at the time "this" was defined.

Let’s take the previous example that gave us trouble initially, and see how changing over to using an arrow function intuitively addresses the problem:

We solved the problem by just using an arrow function.

Conclusion

If you understood all the rules, then pat yourself on the back — you deserve it! Now you are no more someone who is afraid of JavaScript’s most confusing concept — the "this" keyword.

In this article we learned:

  • When calling a function in a standard way shown above, “this” will actually refer to the global object!
  • If the function is contained within an object, then “this” will point to that object.
  • call, apply and bind are functions that are available to us by JavaScript to alter the behaviour of “this” in our program.
  • new keyword or operator when used makes an empty object, then instructs “this” to point to that newly created object
  • Arrow function enables us to lexically bind the “this” keyword in the program, what this means is its value is static and determined by the place where the “this" keyword is defined.

Note of Gratitude

I wanted to take this last opportunity to say thank you.

Thank you for being here! I would not be able to do what I do without people like you who follow along and take that leap of faith to read my post.

I hope you’ll join me in my future blog post and stick around because I think we have something great here. And I hope that I will be able to help you along in your career for many more years to come!

See you next time. Bye!

Discussion (11)

Collapse
lukeshiru profile image
LUKE知る • Edited

#Rule 0. Avoid using this altogether

Trust me. You don't need this and all this edge cases. You can work just fine without it. Avoiding it is far better than any other alternative. Douglas Crocoford recommends this same thing in almost every talk he gives, and I completely agree with him in that regard. Try it, you'll never want to use this again 😊

Collapse
polymathsomnath profile image
Somnath Singh Author

Namaste @lukeshiru
Thank you so much for your response.
Avoiding this in JavaScript is very much possible.

In 2007, there were several research projects that were trying to develop a secure subset of JavaScript. One of the biggest problems was the managing of this. In a method call, "this" is bound to the object of interest, which is sometimes good thing. But if that same function object is called as a function, then "this" could be bound to the global object, which was a very bad thing. They obliterated "this" completely and found that it was not only easier to write code but it was also more cleaner and the language still remained Turing Complete.

I covered that story and how major frameworks like React are getting away from the usage from "this" but the article got quite big, So I edited it out.
Sometimes you have to do the hard things and cut the best parts out and say only what is needed. As the article was on removing the fear that developers have while using "this" keyword, adding anything more made it look tedious.

Writing code in JavaScript without using "this" is a topic by itself and can be covered in a separate article.

I may consider it writing in the future!
Take care, see you in my other post! 🙂

Collapse
lukeshiru profile image
LUKE知る

Looking forward to that future article! ✨

Collapse
xem0n profile image
Xem0n

great post, I love such "under the hood" topics

Collapse
polymathsomnath profile image
Somnath Singh Author

Namaste @xem0n ,
I am glad you liked the article 😊

Collapse
kumarutsav profile image
Kumar Utsav • Edited

Can you please elaborate on determined by the place where the “this" keyword is defined.
What do you mean by this keyword being defined in terms of the counter example based on arrow function?

Collapse
polymathsomnath profile image
Somnath Singh Author

Namaste @kumarutsav ,
Thank you so much for your response!

The "this" object inside an arrow function is lexically bound, which is just a fancy way of saying its value is static and determined by the place where the “this" keyword is defined.

I have used the word lexical here, the word ‘lexical’ means having to do with words or grammar. It deals with where something sits physically in your code that you write.

You see the CS people have a fancy for naming terms so that they sound extra-terrestrial. Lexical just means where to you see it. I can say your fingers are lexically bound to your palm! Do you get what I am trying to say?

So let me ask you a question, where do you see this in the code that has an arrow function? Inside the setInterval function right? We can see the setInterval is inside the start function. So we can say it is a sub-function.

In another case, we saw that once we use this inside a sub-function it is bound to the global object. This happens because, in JavaScript, functions started as a method to the global scope object in our case that is the window object.
This is how the language is designed @kumarutsav . Many feel it is a bug--don't forget the language was designed in 10 days.

This is just the opposite of what one might expect, you use this inside a function in an object and, it works! But the moment you use it inside a sub-function in an object it does not.
So the arrow function that came in ES6 is meant to clear these problems up.
The this in arrow function will bound to the object even if you use it in a sub-function. We no longer need to cache a reference like var self = this as we did in one example.

I hope it clears your doubt! If it does not, then please let me know

Collapse
kumarutsav profile image
Kumar Utsav

My query was not regarding the lexical scoping but about the determined by the place where the “this" keyword is **defined**. How are you defining this keyword?

Thread Thread
polymathsomnath profile image
Somnath Singh Author • Edited

You are not defining the this keyword @kumarutsav , You are making use of it!
The statement just further explains what lexical scoping means.
Read once again, they are connected. 😉

Collapse
tgoneil profile image
Thomas ONeil

Excellent explanation of 'this'! Would love to know how you made this animation:
miro.medium.com/max/1210/1*0wJYjMQ...
Thanks!
Greg

Collapse
polymathsomnath profile image
Somnath Singh Author

Namaste Greg,
I am glad you liked it.
I have used keynote, but you can use any regular presentation software to make something like this. 🙂

Forem Open with the Forem app