DEV Community

gisellec60
gisellec60

Posted on

So,What is "this"?

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()
Enter fullscreen mode Exit fullscreen mode

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())
Enter fullscreen mode Exit fullscreen mode

node.js: global context
Image description

chrome browser: window context
Image description

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
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the this object in getLevel() function represents the school object.

Image description

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())
Enter fullscreen mode Exit fullscreen mode

Image description

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())
Enter fullscreen mode Exit fullscreen mode

Image description

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())
Enter fullscreen mode Exit fullscreen mode

Image description
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)
Enter fullscreen mode Exit fullscreen mode

Image description
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
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

Image description

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 ")
Enter fullscreen mode Exit fullscreen mode

Image description

)
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"])
Enter fullscreen mode Exit fullscreen mode

Image description

bind()

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

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;
Enter fullscreen mode Exit fullscreen mode

We then call the method using the variable:

console.log(level())

Enter fullscreen mode Exit fullscreen mode

Image description

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())
Enter fullscreen mode Exit fullscreen mode

Image description
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())
Enter fullscreen mode Exit fullscreen mode

Image description
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)
Enter fullscreen mode Exit fullscreen mode

Image description
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());

Enter fullscreen mode Exit fullscreen mode

Image description

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.

Top comments (0)