DEV Community

Hridayesh Sharma
Hridayesh Sharma

Posted on • Edited on

What is "this" in Javascript ?

While learning JavaScript there are many roadblocks like closures, asynchronous programming, this keywords, etc. These are the parts of JavaScript that are difficult to understand for a newbie in JavaScript, but once you learn them you can leverage everything JavaScript provides. So today I will be talking about one such superpower and that is this keyword.

So without further delay let's get to it. Before we go into this let's talk about an analogy to understand scope in JavaScript.

An Analogy to Understand Scope in JavaScript

There is a 10 story building and there is a policeman who is looking for a criminal in this building. Now let's see the two ways of how he finds the criminal or what if he does not find the criminal at all. 😨😨

(i) The policeman enters the building and starts looking for the criminal on the ground floor. If he does not find the criminal on the ground floor he goes to the first floor and if he finds the criminal on the first floor he sends him back to police station otherwise he keeps going up one floor at a time until the criminal is caught. And if he does not find the criminal then he reports back to the police station that criminal could not be found in the building.

(ii) This one is interesting πŸ˜‹ There is a way by which the policeman can be directly shot onto any one of the floors and whoever he finds on that floor is the criminal now and there is no way to change that. Such a dynamic way of finding the criminal, isn't it? πŸ˜‚

What do you think which approach can have bad consequences??

Obviously the second approach, as in the first approach what if the real criminal is on another floor and the police just caught a civilian.😫

So with a dynamic mindset now let's try to understand the two different scopes in JavaScript: static or lexical scope and dynamic scope.

Lexical Scope

In our first approach, the scope of finding the criminal is lexical. The policeman first looks on the ground floor and if he does not find the criminal then he goes one floor up and so on. That's exactly how lexical scoping works in JavaScript.

const outer = 12;
function lexical(){
  let inner = 21;
  console.log(inner, outer);
}

lexical(); // 21 12
Enter fullscreen mode Exit fullscreen mode

In the above snippet lexical function first looks for inner variable and it finds it on its own floor. But for outer it finds it own one floor up. So that's how the lexical scope works in JavaScript.

Dynamic Scope

Let's see in code how dynamic scope works.

So here we see instead of alerting 'Gotcha Joe' we got 'Gotcha undefined' when we click on the box. Why is that ?? Why instead of catching the Joe, our policeman (eventHandler function) got undefined. This is because our eventHandler function uses this and depending upon where our handler function is called or invoked this can take different values. There are ways to fix it, I will get to them in a while, I promise.

So far we have understood the scoping in JavaScript and seen how using this can result in unexpected outcomes.

Now let's talk about this', and how to figure out the values ofthis` in our code.

What this actually is?

In JavaScript this is an object inside a function or in a scope which can be any value depending upon how the function is defined or how the function is called.

Let's understand this in different contexts -

case 1 - default this binding

javascript
function printThis() {
console.log(this);
}
printThis(); // in browser it can be window object or in node global object

In the above snippet, the default value of this is what is available inside the function when we try to access it. Now this default value depends on how and where we are calling the function. Here we are calling our function in the global context.

case 2: implicit binding

let obj = {
  name: 'Joe',
  handler: function() {
    console.log(this.name);
  }
}

obj.handler(); // Joe

Here we are implicitly providing the context for this to the function. The value on the left of . is the value of this for our handler function. In this case, it is the object obj itself.

case 3: binding this with apply

function printThis() {
  console.log(this.name);
}

printThis.call({name: 'Joe'}); // Joe

The call method takes the first argument as the value of this that you want to pass to the function and invokes the function. Here we have passed an object with a property name on it. This object will be used as this inside our printThis function.

case 4: the new keyword

The new keyword in JavaScript is used to create a new instance of a class using class syntax or constructor functions. You can read more here in my last post
Understanding Prototypal Inheritance.

So these were different ways of how this works in the JavaScript world. In our click handler example, I promised that I will be telling you different ways of fixing that code so that instead of catching undefined we will be able to catch 'Joe'.

Here is the modified code for that on Codepen

So we have introduced two new ways of handling this

  • fat arrow functions
  • bind method

Let's understand them one by one

fat arrow functions

ES6 introduced a new syntax for writing functions. Though it looks like just syntactic sugar, there is more to it than just new syntax. Fat arrow functions handle this very differently than normal functions. In fat arrow functions this is scoped lexically just like any other variable. We have created fat arrow function version of our previously defined normal functions and now inside our eventHandlerArrowFunction the value of this is the instance of the class itself no matter where the function is called.

bind method

Just like the call method ES5 also introduced the bind method. The difference between the two is that bind takes the value of this as the first argument and returns a new function with this bound to it. Where call invokes the function with the provided value of this along with other arguments.
In our click handler function, we want to pass the reference of the function to addEventListener instead of invoking the function. Therefore we used the bind method there.

So with this, I hope you understood how the mighty this works in JavaScript.

Top comments (2)

Collapse
 
jpmohan1111 profile image
jpmohan1111

In the first code example shouldn't the output of lexical() be 21 12 ?

Collapse
 
vyasriday profile image
Hridayesh Sharma

Yeah, made a typo. Fixed now