Why do code-newbies get confused about the `this` keyword?

Why do code-newbies get confused about the `this` keyword?

Hello world, Akwaaba 👋. The this keyword is one of the most widely used syntax in JavaScript. For most code-newbies, it becomes confusing to understand and properly use the this keyword when writing clean code.

This article will help you understand the this keyword with lots of practical examples.

Let's get started!

What is the this keyword?

When a function is defined, there is a special variable attached to it. That special variable is the this keyword. So, what exactly is the this variable?

The this keyword refers to the object that the function is a property of.

Its main objective is to have access to some value in the `object. However, the value of the this keyword is not static and will always depend on the object that is invoking the function not where it was declared.

The value of the this will only be assigned when the function is actually called or invoked.

Confused, let's take a look at the code below

function findThis(){
console.log(this)
}
/*call the function */
findThis()

Let's now seek to understand the code above

By definition, the this keyword refers to the object the function is a property of.

We then need to ask , what object is the findThis() a property of ? Because the findThis() is invoked in the global context, it is a property of the global object.

Hence, the output of the above code will be in the global object, since we are using a web browser, the global object will be window.

The value of the this in the findThis() will then be

Window {window: Window, self: Window, document: document, name: '', location: Location, …}
  • The this keyword will point to a specific object. To know that object depends on how a function which contains the this keyword is being called.

  • Also note that, the main objective of this keyword in a function, is to find out where to get some value or data from.

Let's take a look at another example

const user = {
    name: 'Emmanuel',
    getName: function(){

        console.log(this.name); 

    }
}


user.getName();
/* the `this` helps  access some data in the object, 
the data we want to access is stored in the `name` key * /

In the code above, we have defined a user object, which has a function getName.

At the time of invocation, the getName function is a property of the user object.

Note that, the value of the this keyword will always depends on the object in which the function is property of at the time of its call. When the getName function is called, it is a property of the user object. In the user object, we can now have access to value of name.

So, the output of this.name will be

Emmanuel

Why is the value of the this keyword not static ?

To understand, why we say the value of the this keyword is not static, let's take a look at the code below:


const user = {
    name: 'Emmanuel',
    getName: function(){
        console.log(this.name)
    }
}
/* assign the getName function to getName  variable */
const getName = user.getName;

const user2 = {
    name: "Stephen",
    getName
}

user2.getName()

Let's see if you can guess the output in the code above, what will the output be ?

The output will be Stephen. Did you get it right?

Let's understand why it is Stephen and not Emmanuel

  • We define the user object and the getName function is a property of the user object

  • We assign the getName function to a variable getName

  • We define the user2 object and sets its property to the getName variable defined earlier.

  • Finally, the getName function is invoked.

By definition, the value of this depends on the object in which the function is called. In other words, the value of this depends on the object which is linked to the invoked function.

Even though the getName function is declared inside the user object, at the time of invocation, the getName function is a property of the user2 object.

What this means is, the value of the this keyword will be accessed from the user2 object and not user.

Keep in mind that, even though we defined the this keyword in the user function, the value of the this keyword is never static. It will always depend on the object calling the function

Finally, in the user2 object, we can now access the name key, and its value will be Stephen.

A perfect way to understand the this keyword is,

Whenever, the function is invoked, check the object before the dot. The value of the this keyword will always be the object before the dot.

If there is no object before the dot, the value of the this keyword will be the global window object.

That said, there are some simple rules that help you which object is referred by the this keyword.

Ways in which functions are called

As stated earlier, the value of this depends on how the function is called, there are three main ways in which functions can be defined and called.

  • Method

  • Simple function call

  • Arrow function

Let's now take a look at the above functions and find out what object the this keyword points to so we can easily find out where to get some data from.

Method

A method is initialized when we attach a function to an object. Take a look a the code below

const user = {
      name: 'Emmanuel',
      year: 1986,
      calcAge: function(){
            console.log('the value of the this  keyword is', this)
      }
}

/*call the method */
user.calcAge()

In the code above, we defined a user object and declared a calcAge method which has a this keyword in its local scope. Now, let's find out what the this keyword in the method points to.

If we invoke the function using user.calcAge(), the output will be as below :

the value of this keyword is {name: "Emmanuel", year: 1986, calcAge: ƒ}
  • From the output above, we can see that the value of the this keyword in the calcAge function will be the user object.

  • We get the this value from the object before the dot (.). The object before the dot is user, hence we get the this value from user object.

  • Since we are only accessing the this keyword, we will have access to the entire user object; which will display all the user properties.

Now, let's expand the code above like below

const user = {
      name: 'Emmanuel',
      year: 1986,
      calcAge: function(){
            console.log(`You are ${2021-this.year} years old`)
      }
}

/* invoke the function, to get the value of the `this` */

user.calcAge()

The output of the code will be

You are 35 years old

Let's break it down to understand what is happening

  • When a method is invoked, the this keyword points to the object. With the code above, the this keyword will point to the user object.

  • Now that we have access to the user object, we also have access to all the properties of the object.

  • this.year will now be evaluated as user.year

  • We can now get the value of user.year as 1986.

  • Writing this.year in the function scope, is way better than writing user.year

When you call a method of an object, JavaScript sets this to the object that owns the method.
With the above, the object that owns the method will be the user

Simple function invocation

When a function is defined in the global context or as a normal function (that is the function is not attached to any object), the value of the this keyword will point to the global window object.

Let's take a look at the code below

function showThis(){
  console.log(this === window)
}
/* call  the function */
showThis()

The output of the above code will be

true
  • The this points to the global window object

Let's find out with the code below:


const calcAge = function(birthYear){
      console.log(2021- birthYear);
      console.log(this)
}

calcAge(1986)

The output will be

35
Window {0: global, window: Window, self: Window, document: document, name: "", location: Location, …}

As you can see, for a function defined in the global scope, the this keyword points to the Window object.

In strict mode, the value of this will be undefined.

this keyword is not static

As stated earlier, the this keyword is not static. Its value will only be determined when the function is being called.

Let's take a look at what that means, using the code below

const emmanuel = {
      year: 1991, 
      calcAge: function(){
            console.log(this);
            console.log(2021 - this.year)
      }
};

/* Define an object */
const matilda = {
      year: 2017
}
/* assign the calcAge fucntion to the calcAge  property  n the matilda object*/
matilda.calcAge = emmanuel.calcAge;

/* invoke the method */

matilda.calcAge()

In the code above:

  • We defined a calcAge method in the emmanuel object

  • We also defined a matilda object

  • We access the value of emmanuel.calcAge function, and also declared a calcAge property in the matilda object, and then assigned the emmanuel.calcAge value to

  • Finally, we called the matilda.calcAge() method

The output will be

{year: 2017, calcAge: ƒ}
 4

As you can see, the output has changed to 4, indicating the value of this is not always constant. The this is always determined by the object calling the method. In the above, the object calling the method will be matilda.

Hence the this will point to the matilda object. In other words, the this always refer to the object before the .

Arrow Function.

Arrow functions do not have their own this keyword. The this keyword in an arrow function is the this keyword of the surrounding function or the parent function.

What it means is the this keyword is picked from the outer lexical scope hence technically referred to as the lexical this.

Let's take a look a the code below

const arrowThis = () => { console.log(this)}

/* invoke the function * /
arrowThis()

The output will be


Window {0: global, window: Window, self: Window, document: document, name: "", location: Location, …}
  • Because arrow functions do not have their own this, it will pick the this from the parent function. The function was defined in the global context

  • In the global context, the this will always point to the window object

Event Listener

If a function is called as an event listener, then the this keyword will always point to the DOM element the handler function is attached to

<button onclick="alert(this.tagName.toLowerCase());">
  Show this
</button>

The this will point to the button element.

In Summary

The this keyword, will never point to the function itself When you call a method of an object, JavaScript sets this to the object that owns the method.

Did you find my article insightful, please help spread the word by sharing it on your social platforms? I would also love to read comments and feedback from you. Me daa se

PS: Akwaaba and Me daa se are Ghanaian 🇬🇭 dialect meaning, Welcome and Thank you respectively ❤️