So,What is "this"?
Tags: this, javascript, execution, context
Published: 2023-05-10 20:14:07

#This 
In short _**this**_ is a special object created by and used in the global/window or function execution context...._what???_ 

Execution context??? Yeah I know..., I hate when someone introduces a term or concept without explaining what it is and how it relates to the current topic, so I'm going to take a little time to explain "**_execution context_**", before discussing the **_this_** keyword.  

**What is an "execution context"?**
When JavaScript begins it creates an environment called the "execution context". The execution context is responsible for transforming and executing code. 

The **_global_** execution context is created when a JavaScript script starts to run, and represents the global scope. A **_function_** execution context is created when a function is called, and represents the function's local scope.

The execution context is made up of two phases: creation and execution.

**_Creation:_** This is when the execution context is created and the environment is setup. Variable and functions values are determined along with the scope chain for the execution context. 

**_Execution:_** This phase is where the code is executed. This is where function calls are evaluated along with any statements or expressions.

Okay, so now that we got that out of the way... what does execution context have to do with "**_this_**"?

Well, I'm glad you _asked_...

The **_this_** keyword represents the object that is executing the current piece of code. Remember we said a global execution context is created when JavaScript first runs? Well, during that time a special object called "**_this_**" is also created and is bonded to the global/window object. Likewise, when a function is invoked the function's execution context is created along with the  **_this_** keyword which is bonded to the object executing the code in the function. 

example:

```
name.f() =>  this.f()
```

**_this_** represents the object which in this case is "name", executing the function. **_this_** always represents the object to the left of the dot.

The value of "**_this_**" depends on the context in which it appears: global, function, or class. Let's take a closer look at **_this_** and the different contexts in which it can be used.

**1.** **_Regular Function_**
In a regular function (_A function this is not the property of an object_), **_this_** is not associated with an object so it evaluates to the window object using the browser and a global object when using node.js. 

```
function show() {
    console.log(this === global);
}
console.log(show())
```

node.js: global context
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92yht5ocfecac5u6oyfc.png)

chrome browser: window context
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/51fsk3rx74r99bkjqblb.png)

**2**. **_Functions as Property of an Object_**
When a function is called as the property of an object, the execution context is created along with the special object called **_this _** which represents the object that owns the function.

```
const school = {
    level: "High School",
    city:  "Bronx",
    getLevel: function () {
          return this.level
    }
}
```
In this example, the **_this_** object in getLevel() function represents the school object. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pid2xzgexzu2pt4dr7c6.png)

Let's take another look at this:

```
const school = {
    level: "High School",
    city:  "Bronx",
    getLevel: function () {
          return console.log(`I went to ${this.level}school, in the ${this.city}`)
    }
}
console.log(school.getLevel())
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mol3bljwgkkrbqlizu91.png)

Notice the code below and the code above both give the same results. You can also see that "**this**" in the code above represents "**school**" below. 

```
const school = {
    level: "High School",
    city:  "Bronx",
    getLevel: function () {
          return console.log(`I went to ${school.level}, in the ${school.city}`)
    }
}
console.log(school.getLevel())
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/969ngssnbbzlzirflplh.png)

**_Remember_**, when you call a function expression that's a property of an object, that function expression's **_this_** object is the object on which the function is called i.e., the object to the left of the dot.
 
**3.** **_Constructor_**
When you use the **_new_** keyword to create an instance of a function object, you use the function as a constructor.  The following example declares a school function, then invokes it as a constructor:

```
function school(level) {
   this.level = level
} 
school.prototype.getLevel = function () {
   return this.level
}

let myschool = new school('Elementary School')
console.log(myschool.getLevel())
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/agknge3165qca9hig55e.png)
The expression new school('Elementary School') is a constructor invocation of the school function. JavaScript creates a new object and sets **_this_** to the newly created object. This pattern works great with only one potential problem. Now you can invoke the school() as a function or as a constructor. If you omit the new keyword as follows:

```
let secondary = school("secondary")
console.log(secondary.level)
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xxh72hi8nuax16cfjt2c.png)
The value in the school() sets the global object, the secondary.level returns undefined.  However to make sure school() is always invoked using constructor invocation:

```
function school(level){
   if(!(this instanceof school)){
      throw Error ("must use the new operator to call the function")
   }
   this.level = level
}
```
ES6 introduced a new property called "**_new.target_**" that allows you to detect whether a function is called as a simple invocation or as a constructor. 

```
function school(level){
   if(!(new.target)){
      throw Error ("must use the new operator to call the function")
   }
   this.level = level
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mdph3g4wmo06ta2k5nil.png)

**4.** **_Explicit_**
There are three ways to override the default context object when calling a function: "call" "apply" and "bind".

**_call()_**
```
function getName(prefix) {
  console.log(prefix + this.name)
}
let stevenson = {
    name:"Stevenson"
}
let monroe ={
    name: "Monroe"
}
getName.call(monroe, "My school is ")
getName.call(stevenson, "My school is ")
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpvnll3ax7wlp5c4aj7r.png)


)
In this example, we called the getName() indirectly using the call() method of the getName function. We passed stevenson and monroe objects as the first arguments of the call() method. The first argument is referred to as the **_thisArg_** object which are bonded to **_this _** inside the function.

**_apply()_**

_**The apply() method is similar to the call() method in that it also requires a **_thisArg_** object to be the first paramenter. Again,  **_thisArg_** object is bonded to the **_this_** keyword inside the function. The only difference between call() and apply() is the second argument passed to apply() is an array:

```
getName.apply(monroe, ["My school is"])
getName.apply(stevenson, ["My school is"])
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3qzxdu4jckxh33nx9wu.png)

**_bind()_**

```
const school = {
    level: "High School",
    city:  "Bronx",
    getLevel: function () {
          return console.log(`I went to ${school.level}, in the ${school.city}`)
    }
}
```

Now a function expression is a property of an object which is a value that can be stored in a variable:

```
let level = school.getLevel;
```
We then call the method using the variable:

```
console.log(level())

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5tfgmuw7pecykbxvrif.png)

Notice we get undefined instead of the level and city. That's because when you call a function expression without specifying its object, JavaScript sets this to the global object in non-strict mode and undefined in the strict mode. To fix this problem we use the bind() method. The bind() method creates a new function whose **_this_** keyword is set to a specified value. We also use a "**_thisArg_**" object as the first argument, which becomes the **_this_** inside the function.

```
let level = school.getLevel.bind(school) 
console.log(level())
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s7ekhco2c8361rhq67qi.png)
In school.getLevel.bind(**_school_**), school is represents  **_thisArg_**.
**_Note:_** Whatever object you bind the variable to it will use:

```
let school ={
   level: "High School",
   city: "Bronx",
   getLevel: function () {return (`I went to ${this.level}, in the ${this.city}`)
    }
}

let college ={
    level: "college",
    city: "Atlanta"
}
let level = school.getLevel.bind(college)
console.log(level())
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efs31db9tvgju5sa2kxj.png)
So we bonded _**school.getLevel.bind**_ to the college object. 

**5.** **_Arrow Functions_**
Arrow functions do not create their own execution context but inherits the **_this_** from the outer function where the arrow function is defined. 

```
let getThis = () => this;
console.log(getThis() === global)
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/44sboxlpbhyrj6n3r07e.png)
The arrow function does not create its own execution content. Remember regular functions when invoked create an execution context that also creates the **_this _**object. Because of this defining a method using an arrow function will cause a problem:

```
function Car() {
   this.speed = 120
}
Car.prototype.getSpeed = () => {
   return this.speed
}
let car = new Car();
console.log(car.getSpeed());

```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/teq7zwz7mntohnsji2e7.png)



**_Conclusion:_**
- Execution Context is responsible for transforming code
-  There are two phases to the execution context: Creation and Execution
-  **_This_** keyword is a special object created during the execution context creation. **_This_** can represents either the object executing the function, the global object or window object.
- The context object can be explicitly set by invoking **_"call"_** on a function and passing it **_thisArg _**as the first argument. This allows for the object to be accessed using **_this_**  from inside the function.
- The context object can also be explicitly set by invoking **_"apply"_** on the function and passing **_thisArg_** as the first argument allowing for the object to be accessed using **_this_** from inside the function.
- The context object can be bonded to a function using the "**_bind_**" method on the function and passing it **_thisArg._** The bind method makes a copy of the function whose **_this_** keyword is bonded to a specified object.