DEV Community

Cover image for New to JS? Understand ‘this’
Amandeep Singh Malhotra
Amandeep Singh Malhotra

Posted on

New to JS? Understand ‘this’

The ‘this’ keyword is a simple concept but can be sometimes tricky to understand by developers who are new to the Javascript environment. Mostly because in JS, the behaviour of this is slightly different than other programming languages (such as Java, for example).

So what’s this?

To put simply, this is a reference to an object. Which object you may ask? Well that depends on the context of the code this is used in. The context depends on the scope where the code was invoked.

Outside functions

If you use this outside of functions, i.e., in the Global Context, this will point to the global object, i.e., the window object. Recall that the window object allows the JS engine to interact with browser’s capabilities and functions. Let’s understand this through examples:

// displays the alert message in the browser
// works the same as window.alert() or just alert()
this.alert("This should alert out message in the browser"); 

// waits for 2 secs, then prints the message on the console
// works the same as window.setTimeout() or just setTimeout()
this.setTimeout(() => {
    // works the same as window.console.log() or just console.log(). You get the pattern now :)
  this.console.log("Hello from the browser");
}, 2000);

var helloObj = "Hello JS"; // declare variable in the global context
console.log(this.helloObj); // prints 'Hello JS' in the console
Enter fullscreen mode Exit fullscreen mode

Within functions

Behaviour of this within functions is same as outside functions, i.e, this will still point to the global object. This is because the function is being called without the context of an object:

var greet = {
  message: "Hello!",
};

function fun() {
  console.log(this.greet.message); 
}

fun(); // 'Hello'
Enter fullscreen mode Exit fullscreen mode

Within methods

Understanding the context of this becomes slightly trickier when used inside methods. Remember - the value of this depends on how the method was invoked and NOT on where the method was defined. For example,

var obj = {
  message: "Hello!",
  printThis: function () {
    console.log(this);  // 'this' points to object 'obj'
  },
};

obj.printThis();
Enter fullscreen mode Exit fullscreen mode

But if we assign the method printThis of obj to another variable, we are executing the method in the global context. Hence this would be assigned to window.

var printThisGlobal = obj.printThis;
printThisGlobal(); // 'this' points to object 'window'
Enter fullscreen mode Exit fullscreen mode

Note how the value of this is dependent on how these functions are invoked.

Important - Inner functions within methods will have global scope since the function would be called without the object’s context:

var data = "Global scope!";

var obj = {
  data: "obj scope!",
  showData() {
    setTimeout(function () {
      console.log(this.data); // prints 'Global Scope!'
    }, 2000);
  },
};

obj.showData();
Enter fullscreen mode Exit fullscreen mode

But what if we want the inner functions to retain the object’s context? Well there are two popular ways to achieve this:

Method 1 - Store the context in another variable:

var data = "Global scope!";

var obj = {
  data: "obj scope!",
  showData() {
        var that = this; // storing the context in the that variable
    setTimeout(function () {
      console.log(that.data); // prints 'obj scope!'
    }, 2000);
  },
};

obj.showData();
Enter fullscreen mode Exit fullscreen mode

Method 2 (My favourite) - Arrow functions:

Arrow functions take the context from the enclosing function, hence are cleaner if we want the function to retain the context of this:

var data = "Global scope!";

var obj = {
  data: "obj scope!",
  showData() {
    setTimeout(() => {
      console.log(this.data); // prints 'obj scope!'
    });
  },
};

obj.showData();
Enter fullscreen mode Exit fullscreen mode

Within constructor functions

When using this within constructor functions (functions created using the new keyword), this points to the newly created object:

function Rectangle(height, width) {
  this.height = height; // this points to the 'Rectangle' object created using the new keyword
  this.width = width;
}

let rectangle1 = new Rectangle(5, 10);
console.log(rectangle1);
Enter fullscreen mode Exit fullscreen mode

Remember to use the new keyword when using constructor functions to avoid setting variables within the function in the global context and subsequently end up polluting it.

Within classes

When used within ES6 classes, this keyword points to the current object created using the new word (this behaviour is similar to constructor functions). Only catch is that since strict mode is enabled by default when using classes, this would point to undefined for functions defined under non-static methods.

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }

  getArea() {
    return this.height * this.width;
  }

  showHeight() {
    setTimeout(function () {
      console.log(this.height); // undefined
    });
  }
}

const rectangle = new Rectangle(5, 10);
console.log(rectangle.getArea()); // 50
rectangle.showHeight(); 
Enter fullscreen mode Exit fullscreen mode

Conclusion

I hope this gives you a fair understanding of how this works in Javascript. Since this is important to understand other concepts in JS, it is extremely imperative that you understand it well.

The strict mode significantly impacts how this behaves, so be sure to check it out.

There are methods which allow you to explicitly set the value of this within objects. These are namely call, apply & bind. You can read more about these methods by clicking on the inline links. I will try to cover more on these methods in a separate article.

If there is something you feel I have missed in this article, do let me know in the comments section below.

References

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode

Top comments (0)