Explaining "this" Keyword In JavaScript Like You're Five
Tags: javascript, beginners, javascriptthis, javascripttutorial
Published: 2023-02-27 17:58:11

`this` is one of the most difficult JavaScript concepts to understand, no doubt about that. If you understood it on your first exposure to it, you're probably one of the greatest JavaScript prodigies to ever walk this earth. Although, if you can't seem to wrap your head around it, don't worry, I'd make you a prodigy.

In this article, You are going to see a substantial amount of code snippets and visual illustrations, this is just to give you a better understanding of JavaScript `this` keyword. The code snippets are not complex, I promise.

## You will learn

* What `this` means in JavaScript and how it works under the hood
    
* `this` in the global scope
    
* `this` in functions and arrow functions
    
* `this` in object methods
    
* `this` in constructor functions
    
* `this` in classes
    
* `this` in event handlers
    
* Best practices when using `this`
    
---

Imagine you are at a smartphone store trying to purchase the latest Samsung device. You found the exact Samsung device and went to the checkout line to finalize the purchase. As you approach the cashier, you noticed a long queue of people waiting to make their own purchases.

After a few minutes, it got to your turn and you show the cashier the Samsung phone you want to purchase, the cashier then begins the checkout process. As the cashier scans the phone and begins to process your payment, you notice that he keeps using the word "this". The cashier writes some stuff on the receipt like "this phone is the latest model" and "this purchase was paid through cash". It made sense to you because he was referring specifically to the phone you were purchasing, not any other Samsung device in the store.

In JavaScript, `this` works in a similar way. When you call a function using an object, `this` refers to the object. So, just as the cashier uses "this" to refer to the specific Samsung device you want to buy, `this` in your JavaScript code refers to the object that invoked the function.


![Visual illustration of how "this" works in JavaScript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nt99ya5ari47rjyzhyiq.jpg)

In the illustration above, when the Samsung object calls the function, `this` in that function references the Samsung object; when the iPhone object calls the function, `this` references the iPhone object.

`this` refers to the object that calls the function at the time of the function call. `this` keyword always refers to either an object, undefined or null. Nothing else.

The code snippet below is a quick example of how `this` works -

```javascript
function thisValue() {
  return this;
}

const newPhone = { 
  name: "Samsung S23 Ultra",
  price: "$900",
};

newPhone.thisValue = thisValue;

console.log(newPhone.thisValue());
// Output: newPhone {name: "Samsung S23 Ultra", price: "$900", thisValue: ƒ}
```

The `thisValue` function was added to the `newPhone` object as a method (functions in an object). Therefore, when the `newPhone` object invokes the `thisValue` method, it returns `newPhone` since `this` refers to the object that calls a function.

Now, let's imagine you want to access the brand of the `newPhone` object, you could create a method that returns the `newPhone` brand, like this `newPhone.name`(works!) or you could say `this.name`(also works!)

```javascript
const newPhone = {
  name: "Samsung S23 Ultra",
  price: "$900",
  thisName() {
    return `I own the ${newPhone.name}.`; // using object name
  },
};

// or

const newPhone = {
  name: "Samsung S23 Ultra",
  price: "$900",
  thisName() {
    return `I own the ${this.name}.`; // using this keyword
  },
};
```

However, there's a slight problem. Since everything in JavaScript (e.g array, functions, etc.) are all objects under the hood, there are times you'd want an object to be created from another object. For example, an object called `oldPhone` can be created from an existing object `newPhone`, like this

```javascript
const newPhone = {
  name: "Samsung S23 Ultra",
  brand: "Samsung",
  touchScreen: true,
  thisName() {
    return `I own the ${newPhone.name}.`;
  },
};

//Object.create() creates an object based on an existing object.
const oldPhone = Object.create(newPhone);
oldPhone.name = "Samsung J5";
console.log(oldPhone.thisName()); // outputs: ???
```

What do you think `oldPhone.thisName()` would output? It outputs: "I own the Samsung S23 Ultra." which shouldn't be because we need the `oldPhone` name and not the `newPhone` name. Since `thisName()` method is already explicitly tied to only return `newPhone` name, trying to call the function with another object (in this case `oldPhone` object) would still return `newPhone.name`.

To correct this, `thisName()` method should reference the name property using `this.name` rather than `newPhone.name` so that it works correctly with any object that has a name property.

```javascript
const newPhone = {
  name: "Samsung S23 Ultra",
  brand: "Samsung",
  touchScreen: true,
  thisName() {
    return `I own the ${this.name}.`; // changed to this.name
  },
};

const oldPhone = Object.create(newPhone);
oldPhone.name = "Samsung J5";
console.log(oldPhone.thisName());
// outputs: I own the Samsung J5. Works as expected
```

Using `this.name` instead of `newPhone.name` is better because it allows the code to be more flexible and reusable. Just know that when you use `this` in an object method, `this` would mostly refer to the object that invokes the method (except for arrow functions, more on that later).

> **_Did you know?_**
> 
> _The `this` keyword is like a hidden parameter that is passed to a function when it is called. You can set the value of `this` to a specific object by using the dot notation (.) to prefix the function with the object. This way, the object that you specified will be used as the `this` context, for example `newPhone.thisValue()`._
> 
> _It's a powerful feature of the language, but it can be tricky to use correctly, so make sure you understand it well._


### `this` In Global Scope

Before we begin, let's have a quick understanding of how `this` works in JavaScript strict mode.

Strict mode is a mode that was introduced to JavaScript for the main purpose of eliminating silent errors and allowing developers to write clean code. You can apply strict mode to your JavaScript by adding `'use strict';` at the top level of your JavaScript i.e before you start coding or doing anything else or at the top level of a function block if you prefer not to apply it to your whole JavaScript code.

Whether in strict mode or not, `this` keyword used at the top level of a script will always refer to the global object(or window object).

Although, when strict mode is used inside a function, and the function is invoked without an object attached to it, `this` would return undefined instead of the global object as the normal JavaScript non-strict mode does. This makes it much easier to spot bugs in the long run.


![Visual illustration of what "this" keyword refers to in strict and non-strict mode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/htvc31ye70mcat2ts6bn.jpg)

Let's see how `this` works in terms of JavaScript scoping. In the global scope, `this` refers to the global object. In a browser environment, the global object is the `window` object, while in a Node.js environment, it is the global object.

These options...

* variables and object properties that are given the value `this` in the global scope,
    
* functions that are invoked in the global scope with no object attached to it,
    

...they all return the global object when assigned to the `this` keyword.

```javascript
let foo = this;
let foo1 = { value: this };
function foo2() { 
  return this;
}

console.log(foo === window); // true
console.log(foo1.value === window); // true
console.log(foo2() === window); // true
```

In the code above, the variable `foo` has `this` keyword assigned to it and since the variable was created in the global scope, the `this` keyword can't refer to any other object so it defaults to the global object.

The variable `foo1` is an object with one of its properties assigned to the `this` keyword. It can be a little tricky since `this` mostly references objects but you have to know that, it is only functions found in an object that works that way. Object properties (not object methods) that are assigned `this` refers to the global object because `this` is not inside a method, it's just in the global scope.

The `foo2` function acts differently though. A function that returns the value of `this` depends on how it's invoked; since the `foo2` function was not invoked as a method of any object, the `this` keyword in the function defaults to undefined (strict mode) or the global object (non-strict mode).

## `this` In Functions & Arrow Functions

Using `this` in a normal function is actually straightforward, the `this` keyword in the function would refer to the object that called it or the object it's bound to, a quick example -

```javascript
//create a function that returns `this`
function playMusic() {
  return `${this.name} is playing music.`;
}

//create objects
const newPhone = {name: "Samsung S23 Ultra"};
const oldPhone = {name: "Samsung J5"};

//copy the function as methods to the object created
newPhone.playMusic = playMusic;
oldPhone.playMusic = playMusic;

console.log(newPhone.playMusic()); //Samsung S23 Ultra is playing music.
console.log(oldPhone.playMusic()); //Samsung J5 is playing music.
```

When the function was copied as a method to the two objects, you might have thought "why not invoke it?". Well if the function was invoked before storing it inside the object, it is the returned value of the function that'd be stored in the object, not the function itself. In essence, doing that would just store a string to `newPhone.playMusic` that'd output "\[object Window\] is playing music." because the function was called with no object attached to it so `this` would default to the global object.

> _❕ Useful Tips_
> 
> _In functions, this refers to the dynamic context in which that particular function is called:_
> 
> * _It can reference the object that invoked it._
>     
> * _It can be explicitly bound to a different object than the one that created it by using call(), apply(), or bind()._
>     
> * _If invoked without the function binding to any object implicitly or explicitly, it references the global object._
>

Now, going through the steps of creating a function with `this` keyword and copying it as a method to different objects can be quite stressful. Instead, you can just create the function as an object method in one object and make other objects call the object method anytime. To achieve this, Javascript has 3 in-built functions that can help with that:

* call
    
* apply
    
* bind
    

These three functions can come in handy when you have an object method that uses `this` keyword to reference and update stuff around that object, but you also need a similar object method like that for other objects. Therefore, rather than creating original object methods for each object, you can simply borrow the object method you need from the object that already owns it. These methods can surely save you a ton of time and effort when working with complicated objects or extensive codebases.

### Using Call

The call function executes a function and explicitly set the `this` keyword to reference a desired object. The syntax is `call(thisArg, ...arguments)` where "thisArg" is the object you want `this` keyword to refer to and "...arguments" are other arguments(separated by a comma) that the object method might need. For example

```javascript
//object with the playMusic method
const newPhone = {
  name: "Samsung S23 Ultra",
  playMusic() {
    return `${this.name} is playing music.`;
  },
};

// objects that need the playMusic method
const momPhone = { name: "Samsung S10" };
const dadPhone = { name: "Samsung A80" };

//using playMusic method for other objects that needs it
console.log(newPhone.playMusic.call(momPhone)); //Samsung S10 is playing music.
console.log(newPhone.playMusic.call(dadPhone)); //Samsung A80 is playing music.
```

The code snippets above have three objects; two objects `momPhone` and `dadPhone` do not have a `playMusic` method, only one object `newPhone` has a `playMusic` method. Now, obviously you'd want all phone objects to be able to play music but creating `playMusic` method for each object can be tasking when dealing with lots of objects. Instead, we kind of took a copy of the `playMusic` method from the object that has it and used it for the two other objects that needed it. The `call()` method makes `this` keyword inside the `playMusic` method to reference the desired object that was passed as an argument to `call()`, instead of the original object that created the method.

### Using apply()

The apply function also invokes an object method that uses `this` keyword and binds it to another object. Although, arguments to be used by `apply()` are passed as a single array unlike `call()`. The syntax is `apply(thisArg, [...arguments])` where "thisArg" is the object you want `this` keyword to refer to and "\[...arguments\]" are other arguments that are passed in an array form that the object method might need. For example,

```javascript
//object with the playMusic method
const newPhone = {
  name: "Samsung S23 Ultra",
  playMusic(song, artist) {
    return `${this.name} is playing "${song}" by ${artist}.`;
  },
};

// objects that need the playMusic method
const oldPhone = { name: "Samsung J5" };
const dadPhone = { name: "Samsung A80" };

//using playMusic method for other objects that needs it
console.log(newPhone.playMusic.apply(oldPhone, ['Calm down','Rema'])); //Samsung J5 is playing "Calm down" by Rema.
console.log(newPhone.playMusic.apply(dadPhone, ['Bad', 'Michael Jackson'])); //Samsung A80 is playing "Bad" by Michael Jackson.
```

By using `apply()` in the code above, we were able to use `this` keyword from the `playMusic` method to reference our desired objects rather than the object that owns the `playMusic` method. We also passed in an array argument to tweak the result a little bit.

> **_Differences between call() and apply()_**
> 
> _They are both incredibly similar with just one difference, which is the way arguments are passed to them._
> 
> * _call() accepts arguments in list-comma separated form -_
>     
>     _`call(thisArg, arg1, arg2, arg3)`_
>     
> * _apply() accepts arguments in a single array-list form -_
>     
>     _`apply(thisArg, [arg1, arg2, arg3])`_
>     
> 
> _Yes, yes, I know what you're thinking. Why would you want to pass an array as an argument when you could just follow the normal way that `call()` uses?_
> 
> _Well, there are instances when you'd need to use `apply()` instead of `call()`. For instance,_
> 
> * _The arguments to be used are being passed dynamically by a server so you don't know the fixed number of arguments to pass._
>     
> * _The arguments you want to use have already been stored in an array._
>     
> * _You might want to use the length of the arguments you passed._
>     
> 
> _Using `apply()` when you come across any of these scenarios would make your JavaScript journey easier._

### Use bind()

If you noticed, when we were using the `call()` and `apply()` functions on the object method, the object method was invoked immediately to reference the desired object as the `this` value. However, in some cases, it might be necessary to bind the `this` value of an object method to a new object without invoking it immediately. In such situations, the `bind()` function can be used.

The `bind()` function creates a new function whereby the object method that uses the `this` keyword would be bound to the desired object passed as an argument. The returned function can then be invoked anytime you wish and `this` would always refer to the desired object that was bounded.

The `bind()` syntax is `bind(thisArg, ...arguments)` where the "thisArg" parameter is the desired object that `this` should refer to & the "...arguments" parameters are the list of arguments(separated by commas) that the function might need.

One of the basic uses of bind() is to create a function that will always be called with a specific value of `this`, regardless of how it is invoked. `this` would never refer to any other object apart from the desired object it was bound to.

```javascript
//object with the accessInternet method
const newPhone = {
  name: "Samsung S23 Ultra",
  accessInternet(hasAccess) {
    if (hasAccess) {
      return `${this.name} can access the internet.`;
    } else {
      return `${this.name} can't access the internet.`;
    }
  },
};

// object that needs the accessInternet method
const oldPhone = { name: "Samsung J5" };

//bind accessInternet method to another object using bind().
//and store the newly created function in a variable
const oldPhoneBound = newPhone.accessInternet.bind(oldPhone, false);
// "oldPhoneBound" function can now be called in any context and at any time,
// its `this` value would always refer to the "oldPhone" object
```

You can think of `bind()` working like this -

```javascript
const oldPhoneBound = (oldPhone) => newPhone.accessInternet.call(oldPhone);
```

JavaScript creates a function for you, then uses `call()` to tie the object method `this` to the desired object. Since codes placed in a function would not run until the function is invoked, `bind()` makes use of that phenomenon

1. It creates a function,
    
2. In the new function body, it places a `call()` function that ties the object method `this` to the desired object and returns it
    
3. The new function can then be stored in any variable and called at any particular time.
    

#### When to use bind()

For instance, when using `this` in a setTimeout, it sometimes doesn't work as expected because setTimeout invokes the function you provided it automatically after a given time.

When setTimeout calls an object method that uses `this`, the `this` keyword would refer to the global object because setTimeout was what called the object method, not the object. Remember, `this` in a function is determined by how the function is called. However, to always make sure `this` points to the right object, `bind()` comes to the rescue

```javascript
function accessInternet(hasAccess) {
  console.log(this)
}

const oldPhone = { name: "Samsung J5" };
oldPhone.hasAccess = accessInternet;

setTimeout(oldPhone.hasAccess, 5000, true); // Global object.
// "oldPhone.hasAccess" was called by setTimeout, 
// `this` loses its context because...
//  oldPhone didn't call the function, setTimeout did...
// `this` defaults to the global object.


//To fix this
function accessInternet(hasAccess) {
  console.log(this)
}

const oldPhone = { name: "Samsung J5" };
//bind "this" to the desired object
oldPhone.hasAccess = accessInternet.bind(oldPhone);

setTimeout(oldPhone.hasAccess, 5000, true) //oldPhone Object

// If call() had been used, the function would have been invoked before you even get a chance to use setTimeout()
```

To avoid unexpected behavior, be cautious when passing functions that use `this` keyword. Errors can occur if `this` context is not properly bound to the object it needs to reference. Binding `this` to the object before passing it around ensures that it always has the expected context.

> **_Fun Fact_**
> 
> _The bound function created by `bind()` can be further bound. Although no matter how many times it is rebounded, `this` would always point to the initial object it bounded to. [You can read more on that here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#transforming_methods_to_utility_functions:~:text=A%20bound%20function,by%20boundFn2.)._

### Using `this` In Arrow Functions

ES6 JavaScript introduced a new type of function called "Arrow Function", which can be written as `let func = () => {}`.

```javascript
const playing = () => true;
```

You've probably heard of this statement "Arrow functions don't have their own `this`". You may wonder, "What does this mean?".

Arrow functions don't follow the rules their sibling(i.e normal functions) follows, whereby `this` value is determined by how the function is called. In arrow functions, `this` refers to the value of its surrounding lexical scope and if none, it defaults to the global object. `this` in arrow function is set to what it was when the arrow function was made.


![Visual representation of how "this" works in arrow functions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qwkh4znjiau7d2f7mhf8.jpg)

Therefore,

* If an arrow function is created in the global scope, `this` value refers to the global object e.g
    

```javascript
// Create an arrow function that returns the value of `this`
const arrowFunc = () => this;

// An object with a `name` property
const newPhone = { name: "Samsung S23 Ultra" };

// Add a method to the object that is set to `arrowFunc`
newPhone.method = arrowFunc;

// call `newPhone.Method`
console.log(newPhone.method()); //global object

// The arrow function is called,
// but since `arrowFunc` was created in the global scope,
// `this` has been binded by default to the global object,
// even though it was called as a method of the `newPhone` object.
```

* If an arrow function is used as an object method, `this` refers to the enclosing lexical scope of the arrow function.
    

```javascript
const newPhone = {
  name: "Samsung S23 Ultra",
  thisValue: this,
  arrowFunc: () => this, //arrow function as object method
};

console.log(newPhone.thisValue); // Output: global object.
console.log(newPhone.arrowFunc()); // Output: global object.
// In this example, `this` in "arrowFunc"...
// is similar to `this` in "thisValue" property...
// which is the enclosing lexical scope, 
// in this case the global object.

// Remember, objects themselves do not have a scope, only functions and blocks in the object are scoped.
```

* If an arrow function is created inside a normal function, `this` value is determined by how the normal function is called e.g
    

```javascript
const newPhone = {
  name: "Samsung S23 Ultra",
  arrowFuncInFunction() {
    let foo = () => this;
    // "foo" is an arrow function in a normal function

    return foo();
  },
};

console.log(newPhone.arrowFuncInFunction()); // Output: newPhone object.
// The arrow function inside "arrowFuncInFunction" method...
// returns the `this` value of its enclosing lexical scope,
// which would be determined by how "arrowFuncInFunction" is called.
```

* If an arrow function is invoked using `call(), apply(), or bind()`, the "thisArg" passed is discarded because the arrow function `this` has already been bounded to the `this` context of its lexical scope.
    

```javascript
// Create an arrow function that returns the value of `this`
const arrowFunc = () => this;

// An object with a `name` property
const newPhone = { name: "Samsung S23 Ultra" };

// use call() to bind `this` to newPhone
console.log(arrowFunc.call(newPhone)); //global object

// This did not work as expected because,
// the "arrowFunc" has automatically bounded `this`...
// to its lexical scope when it was created in the global scope.
// Therefore trying to rebind it using call() would have no effect,
// the output is still the global object.
```

## `this` In Object Methods

Objects Methods in simple terms are functions that are found in objects. Let's use the Samsung phone you purchased earlier as an example, the phone is an object that has object methods(i.e functions) like the ability to play games, watch videos, chat with your ex etc.

> **_Did you know?_**
> 
> _Object curly braces {} are not enclosing lexical scope. They just happened to be used by JavaScript a long time ago before scoping was introduced. They do not define a new scope, only the methods in an object creates a new scope._

Now, when using `this` with objects properties that aren't methods, `this` refers to the global object, while `this` in object methods refers to how the object method is called.

```javascript
const newPhone = {
  // object properties that aren't methods
  name: "Samsung S23 Ultra",
  thisPhone: this,
  // object method
  thisPhoneMethod() {
    return this;
  },
};

console.log(newPhone.thisPhone); // global object
console.log(newPhone.thisName()); // newPhone objet

// "newPhone.thisPhone" property points to the window object...
// because `this` can not be assigned as a value...
// "newPhone.thisPhoneMethod" points to the "newPhone" object...
// because the method was called with the newPhone object.
```

Remember, objects can use the method of another object as their own method. This can be done by directly storing an object method as a property of the desired object, by prototype inheritance, or by using `call, apply and bind` functions.

> **_📍 Note_**
> 
> _Just because a function is created inside an object does not mean the value of `this` in that object method would always refer to the object. `this` in a particular object method can refer to any object that calls that object method._

## Using `this` in callbacks

Oh callbacks, a concept in JavaScript that's also a little bit difficult to understand. Well, for those who don't know, callbacks are basically functions that can be called by another function when passed as an argument to that function, hence the name *callbacks*.

For example, setTimeout accepts a callback function. When setTimeout is called, it automatically invokes the function you passed as an argument at the time specified. Most in-built array methods like map, and forEach all need a callback function as an argument which they execute as soon as they are called.

In a nutshell, closure gets into a function as an argument, the function invokes the callback when called. That's all.

Now, `this` in callbacks are relatively simple, they depend on how the callback is called. If you try to attach an object to a callback, `this` would refer to the context in which the function that executes the callback is called. For example

```javascript
// custom function to execute callback functions
function invokeCallback(callback){
  return callback();
}

const human = {
  name: "Eren Yeager",
  getObject() { return this },
};

invokeCallback(human.getObject); // output: global object
```

Oof, not what you wanted, right?

why does this happen? Well, you passed "human.getObject" as a callback to "invokeCallback" function, and you handed over the invocation rights to "invokeCallback". Remember, `this` is determined by how a function is called, so since "invokeCallback" was the one that invoked the callback function, `this` couldn't find any object to refer to so it defaults to the global object.

To fix this, you'd have to explicitly bind `this` to "human" object.

```javascript
function invokeCallback(callback){
  return callback();
}

const human = {
  name: "Eren Yeager",
  getObject() { return this },
};

// explicitly bind `this` to human object
// bind() returns new function
const boundHumanObject = human.getObject.bind(human);

// pass bounded function as callback for "invokeCallback"
invokeCallback(boundHumanObject); // human object

// works perfectly now.
// No matter what calls the function, `this` would always reference "human" object
```

Some JavaScript inbuilt methods actually allows you to specify the `this` value of a callback as an argument. They allow you to pass both the callback and the `this` value as arguments. A good example would be the map array method:

```javascript
const human = { name: "Jackie Chan" };

// callback function that set abilities to any object
function setAbilities(value) {
  return `${this.name} can ${value}`;
}

// array with abilities for an object
const abilities = ["eat", "fight", "sleep"];

// Use map() to call "setAbilities" with each item on "abilities" array.
// Pass the "human" object as second argument to map(),
// so that `this` in "setAbilities" refers to the "human" object.
const jackieAbilities = abilities.map(setAbilities, human);

console.log(jackieAbilities);
//outputs: ["Jackie Chan can eat", "Jackie Chan can fight", "Jackie Chan can sleep"]
```

Other JavaScript in-built methods that accept `this` as an argument include:

* Array methods - every(), filter(), find(), findIndex(), forEach(), map(), reduce(), reduceRight(), some(), apply(), bind(), call(), match(), replace(), search(), split()
    
* Function methods - call(), apply() and bind()
    
* TypedArray methods - every(), filter(), forEach(), map(), reduce(), reduceRight(), some()
    
* Reflect methods - apply(), construct(), defineProperty(), deleteProperty(), get(), getOwnPropertyDescriptor(), getPrototypeOf(), has(), isExtensible(), ownKeys(), preventExtensions(), set(), setPrototypeOf()
    

## Using `this` In Constructors

In simple terms, constructors are object builders; well, life would have been great if that was all it was, so let's dive in.

Constructors are functions used to create new objects with common properties and methods. Apart from the arrow function, any function can serve as a constructor by invoking it with the `new` keyword.

`this` in constructors would always refer to the new object that the constructor builds when invoked with `new` keyword. In a constructor function, `this` has no context until the constructor is invoked, at which point it becomes the newly created object.

The `this` keyword is a core feature that's needed by constructors to build objects. You can think of how constructors work like this:

```javascript
function Phone(brand, model) {
  // this = {}; (new object created in private by JavaScript)
  this.brand = brand;
  this.model = model;
  // return this; (Javascript returns newly created objects by default.)
}

// When calling the constructor, 
// the 'new' keyword creates a new object
const newPhone = new Phone("Samsung", "Note 9");

// The 'new' keyword creates an empty object,
// and set `this` to the object.
// The constructor copies all properties in it to the empty objects
// by using `this` to refer to the new object.
// The new object is then returned from the constructor.
// The new "newPhone" variable now references the new object that was created.
```

The majority of constructors' names begin with an uppercase letter. It isn't compulsory but just don't be that person.

> **_🚫 Why arrow functions cannot be used as constructors_**
> 
> _The reason why arrow functions can't be used as a constructor is because `this` in arrow functions are auto-bounded to the `this` context of its lexical scope when created. This wouldn't work for a constructor since `this` needs to be bound by `new` keyword to a newly created object which unfortunately arrow functions can't do._

## Using `this` in class

Classes in JavaScript are like blueprints for building objects.

Developers often refer to them as synthetic syntax for function constructors because they provide a more concise and readable syntax for defining constructor functions.

In this article, we're focusing more on how `this` works in classes so going into the nitty gritty details of how constructor works won't be possible (It's quite broad). [Take a deep dive into classes here.](https://javascript.info/classes)

Here is a simple declaration of a class compared to a function constructor

```javascript
// Class Syntax
class Phone {
  constructor(brand, model) {
    this.brand = brand;
    this.model = model;
  }
  getPhoneName() { return `${this.brand} ${this.model}` }
}

//Function Syntax
function Phone(brand, model) {
  this.brand = brand;
  this.model = model;
}
Phone.prototype.getPhoneName = function() { return `${this.brand} ${this.model}` };

// In this example, `this` works the same way in both syntax.
// Although, the class syntax is much better to look at.
```

When dealing with `this` in classes, there are two contexts you need to watch out for: Instance and Static. `this` has different effects in both contexts. I know, it's a lot.

### Instance context

This refers to the properties and methods found in a class that objects created from that class would inherit. In this context, `this` refers to the object the class creates.

Constructors, instance methods, and instance fields are all part of the instance context.

Most of the time, you'd use the instance context because they're the ones that contains all what a class needs to create new objects. Now, as complicated as all these may sound, `this` is actually pretty straightforward in instance context.

Instance context constructors and fields use `this` to refer to the object generated by the class whereas instance method use "this" to refer to the object that called the method (similar to how `this` in object method works).

```javascript
class Game {
  constructor(name, type) {
    this.name = name;
    this.type = type;
  }
  getDetails() {
    console.log(`${this.name} is a ${this.type} game.`);
  }
}

const cod = new Game("COD", "shooting");
const streetFighter = new Game("Street Fighter", "fighting");

cod.getDetails(); // COD is a shooting game.
streetFighter.getDetails(); // Street Fighter is a fighting game
```

`this` works as expected. When the class gets invoked with 'new' keyword(very important), a new object is created by the class and all properties found in the class constructor would be made as properties for the new object. Also, all instance methods of the class would be inherited by the new object using the [prototype inheritance](https://javascript.info/prototype-inheritance).

### Static context

This refers to the properties and methods that's used only by the class or subclasses. In other words, objects created by classes do not have access to information found in the static context. In static context, `this` refers to the class itself.

Static methods, static fields and static initialization blocks are all part of the static context.

The `static` keyword is used to declare a method or field as part of the static context. This is a good way to differentiate methods or fields into to their respective context.

```javascript
class Game {
  // instance context
  constructor(name, type) {
    this.name = name;
    this.type = type;
  }
  getDetails() {
    console.log(`${this.name} is a ${this.type} game.`);
  }

  // static context
  static name = "Class for Game objects";
  static getName() { return this.name }
}

console.log(Game.getName()); // Class for Game objects

// create an object and try to access a static method
const cod = new Game("COD", "shooting");
console.log(cod.getName()); // error: cod.getName is not a function
```

In the code snippet above, when the static method `getName()` is called, it returns the value of the static property name since `this` refers to the class when in static context.

However, when we tried to call `getName()` using an object created by the class, it fails because `getName()` is a static method, which the new object doesn't have access to.

Keep in mind that objects created by a class cannot access static properties or methods; only the class itself and its subclasses can access them.

Like I said, classes can get pretty wild if you're just starting, but no worries you learn as you go (hopefully).

> **_❕ Important_**
> 
> _There's also a popular method that can be found in classes that inherits properties from another class - a method called super()._
> 
> _`super()` is a method that is passed to a class constructor that inherits properties from another class constructor. `this` refers to the object that called super() which is basically the constructor that's about to create a new object._

## Using `this` In Event Handlers

Events and events handlers are features in JavaScript that makes developers add interactivity to a website and as expected, `this` keyword also made its way there. Fortunately, using `this` in event handlers is really straightforward and easy to understand.

Event handlers are functions that are invoked anytime a DOM element trigges an event. The `this` keyword in event handlers refer to the DOM element that triggered the event. This makes it incredibly simple for the event handler to access the properties or methods of the precise DOM element that triggered the event.

A simple code example is

```javascript
//--- HTML Code ---
// <button id="showButton">Hi, I show stuffs</button>
// <button id="hideButton">Hi, I hide stuffs</button>

//--- JavaScript Code ---
const button1 = document.querySelector("#showButton");
const button2 = document.querySelector("#hideButton");

//Event handler function
function handleClick() {
  console.log(this.id);
  console.log(this.innerHTML);
}

button1.addEventListener("click", handleClick);
// output: showButton
// output: Hi, I show stuffs

button2.addEventListener("click", handleClick);
// output: hideButton
// output: Hi, I hide stuffs
```

In this code, two event listeners were added to two buttons. The addEventListener is set to call the `handleClick` function when a "click" event occurs on any of the buttons. When the event occurs, `this` inside the `handleClick` function would refer to the button element that triggered the event. The id and innerHTML of the button can then be accessed through `this`. Therefore, `this` provides an easy way to access information about the specific element that triggered the event.

## Best Practices When Using `this`

Over the years, developers have battled with the fickle nature of `this` so as to find out why it doesn't work as expected in their code. So here are some helpful tips and tricks that you can use to rule over the "this" keyword:

* `this` in functions is determined by how the function is invoked. Alone, this would refer to the global object (non-strict mode) or undefined (strict mode).
    
* Be careful when using `this` in arrow functions, `this` in arrow functions refers to the `this` context of the arrow function lexical scope
    
* `this` in global scope is the global object.
    
* `this` in object methods refers to the object that the method is called upon, not the object that owns the method.
    
* `this` in event handlers refers to the DOM element the event handler is attached to.
    
* `this` is a keyword; you can access what it refers to but you can't assign it a value like how variables do e.g `this = car; // error`
    
* Use `bind`, `call`, or `apply` to explicitly set the `this` value to a desired object of choice. However, keep in mind that these methods cannot change `this` in arrow functions.
    
* When using `this`, use strict mode to avoid unexpected behavior.
    
* Always use `new` when calling a constructor function, if you don't `this` would refer to the global object.
    

---

Wow, it's been a long journey. Thanks for making it to the end! I'm proud of you. If you enjoyed this article, a like would be much appreciated.

Got any questions? Drop them in the comments section, and I'll do my best to help you out.

And hey, if you have any topics or ideas you'd like me to explore, I'm all ears! I'm always available to chat and see what we can create together. Don't hesitate

* Send me a text on Twitter - [@vayo\_tweet](https://twitter.com/Vayo_tweet)
    
* Send me an email - vayospot@gmail.com
    

Now go out there and dominate that project. You've got `this`!