New to JS? Understand ‘this’
Tags: webdev, javascript, beginners, discuss
Published: 2022-07-04 03:44:44

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:

```jsx
// 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
```

### 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:

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

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

fun(); // 'Hello'
```

### 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,

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

obj.printThis();
```

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*. 

```jsx
var printThisGlobal = obj.printThis;
printThisGlobal(); // 'this' points to object 'window'
```

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:

```jsx
var data = "Global scope!";

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

obj.showData();
```

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**:

```jsx
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();
```

**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*:

```jsx
var data = "Global scope!";

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

obj.showData();
```

### Within constructor functions

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

```jsx
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);
```

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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) is enabled by default when using classes, *this* would point to *undefined* for functions defined under non-static methods.

```jsx
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(); 
```

## 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), [apply](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) & [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/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/Operators/this)

[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)