DEV Community

Cover image for "This" keyword in Javascript - an explanation
Arika O
Arika O

Posted on • Updated on

"This" keyword in Javascript - an explanation

What is this and why is it so confusing to understand? Simply put, this keyword refers to the object that is executing the current function (the "owner" of the function). Well ok, now in plain English?

Let's just say that this is dependent on the context in which is used. If we find it in a regular function (we make a simple function call), it references the global object (called window in browsers and global in Node) and if we find it inside a method (a function inside an object), it will reference that object.

For a better understanding, I recommend you try the code below in the console. Note that I'm using the syntax prior to ES6 for writing functions.

function printKeyword() {
  console.log(this);
}

printKeyword(); // prints the window object

const someObject = {
  someProp: 'random',
  someFunction() {console.log(this)}
}

console.log(someObject.someProp) // prints random
someObject.someFunction(); // prints {someProp: "random", someFunction: ƒ}

Enter fullscreen mode Exit fullscreen mode

In the first example, printKeyword it's not a method on an object so, as expected it will print the window object to the console. In the second example, someFunction is a method on someObject, so when trying to log this we'll print the object itself.

If we put it this way, it's not too complicated, right? So why all the fuss? Of course, these are very simple examples so let's take it up a notch.


const myDoggo = {
  name: 'Lulu',
  age: 3,
  hobbies: ['sleeping', 'TV', 'swimming'],

 printName() {
   console.log(this.name)
},

 printAge() {
   console.log(this.age)
},

 printHobbies() {
   console.log(this.hobbies)
},

 printAgeAndHobbies() {
   this.hobbies.forEach(function(hobby) {console.log(hobby + this.age)})
}
}

myDoggo.printName() // prints Lulu
myDoggo.printAge() // prints 3
myDoggo.printHobbies() // prints ["sleeping", "TV", "swimming"]
myDoggo.printAgeAndHobbies() // prints sleepingundefined TVundefined swimmingundefined

Enter fullscreen mode Exit fullscreen mode

We have an object with two properties and four methods. You might notice that the first three methods seem to work perfectly fine but when we get to printAgeAndHobbies we might have a surprise. Trying to log hobby + this.age prints the hobby but not the age. Actually we get undefined.

This is because this.hobbies is inside printAgeAndHobbies, which is a method on the myDoggo object. But this.age is also inside the same method, you might say. Well, yes and no.

this.age is actually inside a call back function which is inside the forEach method inside the printAgeAndHobbies method. Say what? So, we are using a method called forEach. It works with arrays and calls an anonymous function (callback) on every item of the array. So technically, the callback inside which this.age is used is a regular function and not a method on an object. I hope that's clear.

The way we can fix this particular situation is by adding a second parameter to the forEach method (the first one being the call back function). We can pass an object as a second argument and the callback will reference that object. In our case the second argument will be this. As said before, every this we put inside a method on an object refers to that object. Since the second argument will be in the context of the printAgeAndHobbies method, it will reference the myDoggo object. Check the code bellow:

printAgeAndHobbies() {
   this.hobbies.forEach(function(hobby) {console.log(hobby + this.age)}, this)
}

myDoggo.printAgeAndHobbies() // prints sleeping3 TV3 swimming3
Enter fullscreen mode Exit fullscreen mode

I know it's a lot to wrap your head around, so I'm going to stop here for now. If something is still unclear, please ask in the comments and I'll try to give it another shot at explaining. In the next text we'll discuss more fixes and maybe introduce the ultimate fix, the ES6's fat arrow function.

Top comments (0)