DEV Community

Cover image for The `this` Keyword in JavaScript
Youssef Zidan
Youssef Zidan

Posted on • Updated on

The `this` Keyword in JavaScript

In this article, we will remove the confusion of the this keyword in JavaScript.

First, we need to understand the difference between a function and a method.

A function is a block of code to perform a particular task and it Stands Alone.

example:

function sayHello() {
   console.log("Hello")
}
sayHello(); // Hello
Enter fullscreen mode Exit fullscreen mode

A method is also a function but it is inside an object

example:

const person = {
  name: "John",
  sayHello: function(){
    console.log("Hello");
  }
}

person.sayHello() // Hello
Enter fullscreen mode Exit fullscreen mode

So, if this is inside a method, this will refer to the Object itself.

example:

const person = {
  name: "John",
  sayHello: function(){
    console.log(this);
  }
}

person.sayHello();
/*{
name:"John",
sayHello:f sayHello {...}
}*/
Enter fullscreen mode Exit fullscreen mode

And, if this is inside a function, this will refer to the Global Object which is the window Object in Browsers and the global Object in Node.

example:

function sayHello(){
  console.log(this);

sayHello(); //:[object Window]
Enter fullscreen mode Exit fullscreen mode

The Constructor Function.

We use a constructor function to create a blueprint of an Object.
And because of this, the this keyword will refer to the created object.

the new keyword creates a new empty object { }

example:

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

const p1 = new Person("John");
const p2 = new Person("Doe");
p1.log(); 
/* Person {
name:"John",
log: {...}
}*/
p2.log();
/*Person {
name:"Doe",
log: {...}
}*/

Enter fullscreen mode Exit fullscreen mode

The Confusion Starts Here.

Consider this code and try to guess what the this will refer to.

const person = {
  fName: "John",
  skills: ["HTML", "CSS", "JS"],
  logSkills: function(){
    this.skills.forEach(function(skill){
      console.log(`${this.fName} can do ${skill}.`)
    })
  }
}

person.logSkills();

Enter fullscreen mode Exit fullscreen mode

Is your answer =>
John can do HTML
John can do CSS
John can do JS
?

Unfortunately, your answer is wrong.

the correct answer is =>
undefined can do HTML
undefined can do CSS
undefined can do JS

since this.fName will be undefined.
because this will refer to the window object, and window.fName is undefined.

But why you may wonder? isn't function(skill){ } is inside the person object?

Well, this not quite right.
The this is inside a callback function.
And a callback function is just a regular function.

So, this will definitely refer to the window object.

That's why we tend to use Arrow Functions as callback functions Since it Does not have its own bindings to this.

Now when we substitute a regular callback function to an Arrow Function you will get the result you expected.

const person = {
  fName: "John",
  skills: ["HTML", "CSS", "JS"],
  logSkills: function(){
    this.skills.forEach((skill)=>{
      console.log(`'${this.fName}' can do '${skill}'.`)
    })
  }
}
person.logSkills();
/*
John can do HTML.
John can do CSS.
John can do JS.
*/
Enter fullscreen mode Exit fullscreen mode


LinkedIn

Top comments (8)

Collapse
 
andreacanton profile image
Andrea Canton

Thank you for sharing! For retro compatibility you can use bind() on the function passed as argument at the forEach

Collapse
 
youssefzidan profile image
Youssef Zidan

That's correct!
Thank you.

Collapse
 
ibrahimkamal profile image
Ibrahim Kamal

thanks ya handasa tslam edak ♥♥

Collapse
 
youssefzidan profile image
Youssef Zidan

7abeby ❤️

Collapse
 
tanmayc07 profile image
Tanmay Chaudhari

Makes sense! Thank you for the simple explanation🙌

Collapse
 
youssefzidan profile image
Youssef Zidan

You are welcome ^_^

Collapse
 
erdbzn profile image
ΣRD βΩISΩΠ

Good job

Collapse
 
youssefzidan profile image
Youssef Zidan

Thank you.