beginner

Understanding `this`


In simple terms, the this keyword refers to the object. You are always “binding” some object to where this is called. What object you are binding depends on the context.

Global Context

In the global context, this refers to the global object, which is often window in web browsers and global in NodeJS (but both depend on strict mode, configuration,…). What this means is basically whenever you call this in the global context you are “binding” a global object to be this.

console.log(this === global); // In NodeJS, this should be true*
console.log(this === window); // In JS in browser, this should be true*

// * - depends on configurations...

Function Context

Here we have two different examples, where this refers to different objects. This is because the function itself is executed in different contexts. Generally, this is an object that called the function.

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

test(); // window object in browser JS

Above, we are taking our default object window and “binding” it to this. This happens automatically.

const person = {
  name: "Mario",
  greet: function () {
    console.log(`Hello ${this.name}`);
  },
};
person.greet(); // Output: "Hello Mario"

But here, we have another object person that is automatically being bound to be this and then it makes sense that this.name is Mario.

function hello() {
  console.log(`Hello ${this.name}`);
}

const person = {
  name: "Mario",
  sayHello: hello,
};

hello(); // Output: Hello undefined
person.sayHello(); // Output: Hello Mario

Another example that shows that if we execute hello directly then this does not contain name property (even if it is window object in case of browser) and we get undefined. However, if called in context of person object then that object gets bound to this.

Arrow Functions

Arrow functions behave differently with the this keyword even if in some cases it appears its not. This is related to something called lexical scope(⏭️). Whereas before we have an object that called the function bound to this, with arrow functions this is always the object that defined the arrow function.

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

const second = () => {
  console.log(this);
};

first(); // window/global/undefined
second(); //window/global/undefined

Above, the results are the same for both. But lets look at next examples:

const person = {
  name: "Mario",
  greet: () => {
    console.log(`Hello, my name is ${this.name}`);
  },
};
person.greet(); // Output: "Hello, my name is undefined"
const person = {
  name: "Mario",
  greet: function () {
    const inner = () => {
      console.log(`Hello, my name is ${this.name}`);
    };
    inner();
  },
};
person.greet(); // Output: "Hello, my name is Mario"

Some parts below are copied from freeCodeCamp as it is very nicely explained.

When inside an object, the this keyword refers to the current object only when you declare the method using the standard syntax (methodName() or methodName: function(){ }) .When you declare an object method using the arrow function, the this keyword refers to the global object. Never use the arrow function when declaring a method. However, you can do something like this:

const person = {
  name: "Nathan",
  skills: ["HTML", "CSS", "JavaScript"],

  showSkills() {
    this.skills.forEach(function (skill) {
      console.log(`${this.name} is skilled in ${skill}`);
    });
  },
};

person.showSkills();
// Outputs:
// undefined is skilled in HTML
// undefined is skilled in CSS
// undefined is skilled in JavaScript

Here, the this keyword refers to the window object because we called the showSkills() method outside of the person object.

In the global object, the name property is undefined.

const person = {
  name: "Nathan",
  skills: ["HTML", "CSS", "JavaScript"],

  showSkills() {
    this.skills.forEach((skill) => {
      console.log(`${this.name} is skilled in ${skill}`);
    });
  },
};

person.showSkills();
// Outputs:
// Nathan is skilled in HTML
// Nathan is skilled in CSS
// Nathan is skilled in JavaScript

Here, the this keyword refers to the object from which the arrow function is defined, which is the person object.

This one behavior is what makes people prefer arrow functions, because it makes more sense to have this refer to the object from which you define that function rather than from which you call it.

What now?

Now you have the ability to expand your existing code and use this. Try to use above examples as a insipiration on what to try out next.

Next Understanding closures