# Understanding The  "this" Parameter In JavaScript Once And For All

The ```this``` parameter in JavaScript is like that oddly concealed obstacle on a path that keeps tripping people. For the JavaScript beginner, it is often a thing of much unclarity, while for many a fairly-seasoned developer, it is one of those things they've figured out how to use but have never *truly* understood.

The ```this``` parameter is a vital ingredient in object-oriented JavaScript and a deep understanding of how it behaves is key to unlocking so many other concepts. By the end of this article, you should have gotten the insight needed to forever dispel any uncertainty you may have on ```this``` subject matter (*pun so intended*).

<br />
# What exactly is "this"?

When a function is invoked, in addition to the explicit arguments passed to it, it receives other implicit parameters under the hood that are accessible within the body of the function. One of these is the ```this``` parameter which represents the object that is associated with the function invocation. It is often referred to as the **function context**.

However, ```this``` and the way it is determined is one of those things in JavaScript that are not so straightforward. The value of ```this``` is not only dictated by how and where a function is defined, but also, largely by how it is invoked. To begin making heads or tails of how ```this``` in a function is determined, we have to revisit our knowledge of function behavior.

<br />
# Invoking functions

There are four ways functions can be invoked in JavaScript, each with its own peculiarity:

1. As  a  function—```averageJoe()```,  in which the  function  is  invoked  in  a  straightforward manner
2. As  a  method—```averageJoe.talk()```,  which  ties  the  invocation  to  an  object,  enabling object-oriented programming
3. As a constructor—```new AverageJoe()```, in which a new object is brought into being
4. Via the function’s apply or call methods—```averageJoe.call(someObject)``` or ```averageJoe.apply(someObject)```

*— Secrets of the JavaScript Ninja, Second Edition*

## As a function

When a function is invoked in a straightforward manner, its function context (that is, the ```this``` value) can be two things. In non-strict mode, the global context (the ```window``` object) becomes the function context. In strict mode, it will be ```undefined```.


```
function averageJoe() {
    console.log(this)
}

function strictJoe() {
    "use strict"
    console.log(this)
}

averageJoe()  //  window object
strictJoe()  //  undefined
```

The outcome is the same even if the function is defined within a function, so long it is invoked in a straightforward manner:

```
function outer() {
  function inner() {
    console.log(this)
  }

  function strictInner() {
    "use strict"
    console.log(this)
  }

  inner()  //  window object
  strictInner()  //  undefined
}
outer()
``` 

## As a method

Functions can also be properties in objects and in that capacity, they are known as methods. When a function is invoked through an object (as a method), the object itself becomes the function context and is accessible within the body of the method via the ```this``` parameter.

```
averageJoe = {
  name: "Joe",
  talk: function() {
    console.log(this)
  }
}

averageJoe.talk()  //  {name: "Joe", talk: ƒ}
``` 

## As a constructor

[Constructor functions](https://javascript.info/constructor-new) are essentially the same old, run-of-the-mill functions we've been dealing with. As the name implies, we use them to "construct" new objects. To invoke a function as a constructor, we precede the function invocation with the ```new``` keyword.

When a function is invoked with the ```new``` keyword, a new object instance is created and provided to the function as its context. Within the function, any reference to ```this``` is a reference to the newly created object instance.

```
function AverageJoe() {
  console.log(this)  //  {} 'new object'
  this.name = "Joe"
  console.log(this)  //  {name: "Joe"}
}
new AverageJoe()
``` 

##  Via the apply or call method

Functions in JavaScript have access to two inbuilt methods: [apply](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) and [call](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call).

```
func.apply(thisArg, argArray)

func.call(thisArg, arg1, arg2, ...)
```

They allow us invoke a function and explicitly tie it to an object. Any object supplied to the ```thisArg``` parameter becomes the function context and what is referenced by ```this``` within the function.

```
let averageJoe = {
  name: "Joe"
}

function randomGuy() {
  console.log(this)
}

randomGuy.call(averageJoe)  //  {name: "Joe"}
```

<br />
# Taking a closer look at functions

Functions being first-class objects in JavaScript mean they can, among other things, be assigned to things and passed around just like other value types. Of course, being objects, when we do assign or pass them around, what we are actually passing is their reference.

This flexibility around functions creates plentiful variety in the manner in which they are applied and used. Let's see how the concepts we've covered so far come into play in some of these scenarios.

```javascript
function loneGuy() {
  console.log(this)
}
loneGuy()  //  window object


let averageJoe = {
  name: "Joe",
  talk: loneGuy
}
averageJoe.talk()  //   {name: "Joe", talk: ƒ}


let anotherAverageJoe = {
  name: "Another Joe",
  speak: averageJoe.talk
}
anotherAverageJoe.speak()  //  {name: "Another Joe", speak: ƒ}


let anotherLoneGuy = anotherAverageJoe.speak
anotherLoneGuy()  //  window object


anotherLoneGuy.apply(averageJoe)  //  {name: "Joe", talk: ƒ}
averageJoe.talk.call(anotherAverageJoe)  //  {name: "Another Joe", speak: ƒ}
```
<br />

We begin by defining a function ```loneGuy``` that logs the current value of ```this``` within its function body:

```
function loneGuy() {
  console.log(this)
}
```

When invoked as an ordinary, standalone function, the ```window``` object is outputted as the value of ```this```:

```
loneGuy()  //  window object
```

We go on to create an object that has a ```talk```  method that references the ```loneGuy``` function. When the ```talk``` method is invoked, its parent object, ```averageJoe``` now becomes the ```this``` value:

```
let averageJoe = {
  name: "Joe",
  talk: loneGuy
}
averageJoe.talk()  //   {name: "Joe", talk: ƒ}
```

We create another object ```anotherAverageJoe``` whose ```speak``` method is a reference to ```averageJoe.talk```. The ```speak``` method is invoked via its parent object ```anotherAverageJoe```, which is rightly outputted as the ```this``` value.

```
let anotherAverageJoe = {
  name: "Another Joe",
  speak: averageJoe.talk
}
anotherAverageJoe.speak()  //  {name: "Another Joe", speak: ƒ}
```

We create a new variable ```anotherLoneGuy``` and pass it a reference to ```anotherAverageJoe.speak```. We go ahead to invoke it in a straightforward manner and sure enough, it gets the ```window``` object as its ```this``` value.

```
let anotherLoneGuy = anotherAverageJoe.speak
anotherLoneGuy()  //  window object
```

Next, we invoke the newly created ```anotherLoneGuy``` via the built-in ```apply``` method and explicitly provide ```averageJoe``` as its function context. Expectedly, it runs and logs ```averageJoe``` as its ```this``` value. We also invoke ```averageJoe.talk``` via the ```call``` method and provide ```anotherAverageJoe``` as its function context which it duly outputs as its ```this``` value, despite being a method in ```averageJoe```.

```
anotherLoneGuy.apply(averageJoe)  //  {name: "Joe", talk: ƒ}
averageJoe.talk.call(anotherAverageJoe)  //  {name: "Another Joe", speak: ƒ}
```

From all the passing around and reassigning of our initial function, we can see that whilst where and how a function is defined may have a hand in how its ```this``` value is arrived at, how it eventually gets invoked is the most determining factor.

<br />

# The curious case of arrow functions

[Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) came with ES6 and brought new elegance to how functions were wielded in JavaScript. They discarded some of the syntactic baggage of traditional functions and allowed functions to be expressed more succinctly and lucidly.

Arrow function expressions weren't just a syntactic retailoring of traditional functions though. They differed not only in syntax but slightly in behavior as well, one of which being how function context is determined. Arrow functions don’t have their own ```this``` value. Instead, they remember the value of the ```this``` parameter at the time of their definition.

Let's understand this by walking through some code.

```
function randomGuy() {
  function regularFunc() {
    console.log(this)
  }

  const arrowFunc = () => {
    console.log(this)
  }

  regularFunc()
  arrowFunc()
}
randomGuy()
//  regularFunc –> window object
//  arrowFunc –> window object


let averageJoe = {
  name: "Joe",
  talk: randomGuy
}
averageJoe.talk()
//  regularFunc –> window object
//  arrowFunc –> {name: "Joe", talk: ƒ}
```
<br />

To begin, we define a ```randomGuy``` function, inside of which we house two other functions—a normal function ```regularFunc``` and an arrow function expression ```arrowFunc```—both of which log the value of ```this``` inside their respective bodies. 

```
function randomGuy() {
  function regularFunc() {
    console.log(this)
  }

  const arrowFunc = () => {
    console.log(this)
  }

  regularFunc()
  arrowFunc()
}
```

We invoke ```randomGuy``` the straightforward way and its function context becomes the ```window``` object. The code executes beyond the function definitions and reaches the ```regularFunc``` invocation. It is also invoked in a straightforward fashion, thus, it gets the ```window``` object as its function context as well. Next, ```arrowFunc``` is invoked and as an arrow function that doesn't determine its own ```this``` value, it takes on the ```this``` value existing at the time it was defined, which was the ```window``` object.

```
randomGuy()
//  regularFunc –> window object
//  arrowFunc –> window object
```

> It is vital to understand the nuance here. Even though both functions ended up with the ```window``` object as their respective ```this``` values, the reasons were different. For ```regularFunc``` it was because it was invoked in straightforward manner, while for ```arrowFunc``` it was because the ```window``` object was the existing ```this``` value at the time of its definition and that was what it stuck with.

<br />
We go on to define an object ```averageJoe``` which has a ```talk``` method that is a reference to ```randomGuy```.

```
let averageJoe = {
  name: "Joe",
  talk: randomGuy
}
```

When the ```talk``` method is invoked, the ```this``` value within its body becomes its parent object ```averageJoe``` through which it was invoked. We go past the function definitions and once again, ```regularFunc``` gets invoked in straightforward fashion making the ```window``` object its ```this``` value. Next, ```arrowFunc``` is invoked, and being an arrow function, it remembers the ```this``` value that existed at the time it was defined (the ```averageJoe``` object) and inherits it as its own ```this``` value.

```
averageJoe.talk()
//  regularFunc –> window object
//  arrowFunc –> {name: "Joe", talk: ƒ}
```

Arrow functions get their function context from the existing function context at the time of their definition. They remember this context and stick faithfully to it no matter how they're invoked later on.

## Arrow functions as callbacks

An area where the practicality of arrow functions comes to bear is in the use of callback functions. Traditional functions have always been quirky in this regard and prior to arrow functions, developers had to resort to workarounds when using them as callbacks in certain cases. Take a look at this code for example:

```
let averageJoe = {
  hobbies: ["reading", "coding", "blogging"],
  printHobby: function(hobby) {
    console.log(hobby)
  },
  printHobbies: function() {
    this.hobbies.forEach(function(hobby) {
      this.printHobby(hobby)
    })
  }
}
averageJoe.printHobbies()  //  Uncaught TypeError: this.printHobby is not a function
```

In this scenario, using a traditional function expression as our callback brought us nothing but heartbreak. When the anonymous callback function we passed to the ```forEach``` method gets invoked, it takes on the ```window``` object as its function context and which, of course, isn't where the ```printHobby``` method resides. Hence, the error we got.

However, when we make use of an arrow function instead, we see that it captures the prevailing ```this``` value at the time of its definition (the ```averageJoe``` object) and this, in turn, leads to the output we desire:

```
// ...

  printHobbies: function() {
    this.hobbies.forEach(hobby => {
      this.printHobby(hobby)
    })
  }
}
averageJoe.printHobbies()  //  "reading", "coding", "blogging"
```

## Using arrow functions as methods

You should be a bit careful with arrow functions. Their characteristic of inheriting the ```this``` parameter leads to a quirk when we use them as methods.

Take this for example:

```javascript
let averageJoe = {
  name: "Joe",
  talk: () => {
    console.log(this)
   }
}

averageJoe.talk()  //  window object
```

Within the ```talk``` method, ```this``` now references the ```window``` object as opposed to its parent object ```averageJoe```. Crazy, right? Don't panic, I will explain.

It's actually quite simple. Arrow functions always sticking to the ```this``` value existing at the time of their definition means that they won't take their parent objects as their function context when they're invoked through them as methods. In this particular case, ```averageJoe``` is created in global JavaScript code (that is, not within a function) where the value of ```this``` is the ```window``` object and that is what the arrow function expression used for the ```talk``` method stuck with.

This same behavior of arrow functions leads to a different outcome when we come to constructor functions:

```
function AverageJoe() {
  this.name = "Joe"
  this.talk = () => {
      console.log(this)
    }
}

let averageJoe = new AverageJoe()
averageJoe.talk()  //  {name: "Joe", talk: ƒ}
```

As we know, invoking constructor functions with the ```new``` keyword leads to a new object instance being created and made the function context. So, in essence, the object that we are passing the arrow function to as a method is also the existing function context at the time it was defined and that is what it will stick to whenever it is invoked.

In fact, *however* it is invoked.

```
averageJoe.talk()  //  {name: "Joe", talk: ƒ}

let loneGuy = averageJoe.talk
loneGuy()  //  {name: "Joe", talk: ƒ}  not window object

averageJoe.talk.call(window)  //  {name: "Joe", talk: ƒ}  still not window object

let anotherLoneGuy = averageJoe.talk.bind(window)
anotherLoneGuy()  //  {name: "Joe", talk: ƒ}  lol, still not window object
```

> On a quick note, you shouldn't use arrow functions as methods as they aren't fit for that purpose. This was only for demonstration purposes.

<br />
#  Conclusion

We've covered ample ground on this topic. We started off by getting to know what ```this``` was. We looked at functions, the variety of ways they are invoked, and how they affect how ```this``` is determined. We also took a good look at arrow functions and their interesting peculiarities.

Hopefully, this article has done enough to demystify and help you understand the ```this``` parameter once and for all. Thanks for reading!
