The Behaviour of the 'this' Keyword In Traditional Functions vs. Arrow Functions

The Behaviour of the 'this' Keyword In Traditional Functions vs. Arrow Functions

The 'this' keyword is one of the most confusing aspects of the JavaScript language. Many developers find themselves puzzled by its behaviour and struggle to understand what it represents. If you've faced this issue as well, rest assured, you're not alone.

After reading this blog, I can guarantee that your understanding of the 'this' keyword will be much more clear.

The behaviour of 'this' In Traditional Functions

JavaScript's 'this' keyword used in a function refers to the object it belongs to. I know you have heard this sentence a thousand times. Just kidding, it might be a few times :) Let's see what it really means.

Before understanding the 'this' keyword, let's look at the simple function calls.

fucntion sayMyName(name){
    console.log(`My name is ${name}`);
}
sayMyName("Abhijeet")

Looking at the function, if I were to ask you what the value of the name parameter is, you would say it entirely depends on what is passed to the function when calling it. In this case, I have passed my name as "Abhijeet", so its value is "Abhijeet". If I were to pass "Rahul", its value would be "Rahul".

Similarly, in traditional JavaScript functions, the value of the 'this' keyword is entirely dependent on how the function is called.

There are four ways to determine the value of the 'this' keyword:

  1. Implicit binding

  2. Explicit binding

  3. New binding

  4. Default binding

Don't worry, we will look at each of these, one by one.

  1. Implicit binding

When we call a function by object.function() syntax, this is called implicit binding and the 'this' keyword represents the object to the left of the function.

const person = {
    name: 'Simran',
    sayMyName: function () {
        console.log(this)
        console.log(`My name is ${this.name}`)
    }
}
person .sayMyName()
  1. Explicit Binding

Every function in JavaScript has a property 'call'. We can use this property to call the function with an object passed as a parameter. And the object which is passed as a parameter represents the 'this' keyword for that function call.

For example, in the below code example, there are two persons person1 and person2 with properties name and city. And we have one function which prints the 'this' keyword and the name. Let's say we want to print the name of a person2 then how can we do it?

We can call the function with the 'call' property and pass the object person2 as a parameter.

Explicit binding makes functions reusable for multiple objects.

function sayMyName (){
        console.log(this)
        console.log(`My name is ${this.name}`)
}
const person1 = {
    name: "Abhijeet",
    city: "Chandigarh,The City Beautiful",  
}
const person2 = {
    name: "Rahul",
    city: "Mohali",
}
sayMyName.call(person2)
sayMyName.call(person1)
  1. New Binding

In JavaScript, we have constructor functions that we can call with a new keyword to create different objects of similar properties and methods. In the below example, we have a Person constructor which has been used to create two persons person1 and person2 of the same property that is name and age but different values.

When we call the function with a new keyword the value of the 'this' keyword is an empty object {} and then properties defined in the function using the this.property = value syntax are putten inside the { } object and then it is returned automatically.

function Person(name,age){
    console.log(this)
    this.name = name;
    this.age = age; 
}

const person1 = new Person('Simran', 21)
const person2 = new Person('Rahul', 20)
  1. Default Binding

If none of the above conditions is met, default binding comes into the picture, and the 'this' keyword refers to the global 'Window' object in the case of browsers and [global this] in the case of node environment. Or simply we can say in normal function calls 'this' keyword refers to the global 'window' object.

function sayMyname(name){
    console.log(name)
    console.log(this)
}

sayMyname("Abhijeet")

Order of precedence for this Keyword

  • New binding

  • Explicit Binding

  • Implicit Binding

  • Default Binding

First, it is checked whether the function is called with a 'new' keyword if yes then it represents an empty object { } if not then it is checked for explicit binding, after that it is checked for Implicit binding. If these three conditions do not meet then 'this' represents a global 'window' object.

The Behaviour of 'this' In Arrow Functions.

The behaviour of the 'this' keyword in arrow functions is quite different from the traditional functions. In traditional functions, this keyword depends on how the functions are called while in arrow functions 'this' keyword is evaluated based on where the arrow function is located.

Arrow functions themselves don't have the 'this' keyword instead they use the value of their parent 'this'. I know it is confusing. The key point to remember here is that in arrow functions 'this' keyword is not dependent on how the function is called but instead on where the function is defined and who is its parent.

Let's see using example. Looking at the function call you might think it will print the fan object but again I will repeat, it doesn't depend on how it is called instead where it is located. In this case, it is located inside a fan object and the 'this' keyword for a fan object is 'window' therefore its output will be the 'window' object.

You must be thinking why 'this' refers to the 'window' for the fan object, right? Because the fan object is defined inside the global context and in the global context 'this' refers to the 'window' object.

const fan = {
    type: 'table',
    price: 2000,
    printFan: ()=>{
        console.log(this)
     }
}
fan.printFan()

Let's change the above example slightly. Now the arrow function printFan is defined inside the traditional function, therefore, the fanDetails function is the parent of the printFan function. If you didn't understand read again slowly slowly.

Now we are calling the parent function fanDetails using the implicit binding, therefore, the 'this' keyword for the parent function will be the fan object. And as we discussed above arrow functions don't have their own 'this' keyword instead they use their parent 'this'. Therefore, the 'this' keyword for the printFan function will also be the fan object.

const fan = {
    type: 'table',
    price: 2000,
    fanDetails: function(){
        console.log('This keyword for parent fn: ', this)
        const printFan = ()=>{
            console.log('This keyword for child fn: ', this)
        }
        printFan();
    }

}
fan.fanDetails()

Another difference between arrow functions and traditional functions is that we can't call arrow functions using the 'new' keyword. Therefore, they cannot be used to create factory functions.

If you've reached this point, please leave a comment letting me know if this blog has helped you understand the concepts related to the 'this' keyword better. Your feedback is important to me and will help me know if the blog has been effective in clearing up any confusion you might have had about the 'this' keyword.

Thank you for your time and input!