DEV Community

Ozoemena
Ozoemena

Posted on • Updated on

Understanding the “this” keyword and Execution Context

Introduction

If you had read my previous article, you would have understood that scope is simply a set of rules that controls how reference to a variable is resolved.
In this article, you will learn

  • The meaning of Execution context

  • How it differs from the scope

  • “this” keyword

  • Type of Execution context

  • Phases of Execution Context creation

Execution Context

Aside from scope, another characteristic that determines what a function can assess and cannot assess is the execution context. Execution context is simply an environment created by the JavaScript engine that contains all the codes to be executed and all that is needed for that execution to take place.
A function is exposed to an execution context via its “this” keyword. The "this" keyword is like a link that connects a function to its execution context and as such determines the variable it can and cannot assess. “this” is a dynamic characteristic of a function which is determined any time a function is called.
Both scope and execution context are objects, the difference is that while execution context is like a tangible object whose properties are available to a function anytime it is called, a scope is an object hidden in the JavaScript engine and does not change and its property takes the form of identifier variable which is available inside the function.

Type of Execution Context

  1. Global Execution Context (GEC)
  2. Functional Execution Context (FEC)

Global Execution Context, GEC

This is the default execution context in that it is the first environment created when a JS code is first received, as such there can be only one Global Execution Context (GEC) within a JavaScript file. It is the environment where all codes that are not inside a function are executed.

Function Execution Context, (FEC)

This is the environment created to execute the code within the GEC whenever a function is called. In other words, GEC includes both the codes that are inside and outside a function while FEC contains only the code inside a function. Since there can be more than one function in a JS file, there can be more than one FEC in a GEC.

Phases of Execution Context creation

  1. Creation phase
  2. Execution phase

Creation Phase

During the creation phase, the EC is associated with the Execution Context Object, ECO. The ECO is where all the data needed for the execution of the code is stored. The creation phase is in 3 stages
a. Creation of the variable object (VO)
b. Creation of the scope chain
c. Setting the value of the "this" keyword

a. Creation of Variable Object, VO

The VO is like a container that stores all the variables and function declarations defined within the execution context. When we use the var keyword to declare a variable, a property is added to the VO which points to the variable and is set to undefined. This property is stored in the memory. This means that once a function is declared, it is stored in memory and made accessible in the variable object even before the code starts running. This is called hoisting.
Hoisting implies the process in which variable and function declarations are stored even before the code is run.
FEC does not create a VO, rather it generates an array which holds all the arguments needed by that function.
Both function and variable declaration are hoisted, this means that they are both stored in memory of the EC’s variable object and made available within the EC even before the code runs. This is the reason why a developer can choose to declare a function before calling it or call a function before declaring it. Both will still work as the browser will declare a function first due to hoisting before being called.
In variable hoisting, when a variable is declared with the var keyword, it is stored in the Execution Context’s memory and a property is assigned to it with its initial value set to undefined. This is the reason why trying to assess a variable before it is defined will give you undefine.

console.log(greetings)
var greetings = “Hello world”  // undefined.
Enter fullscreen mode Exit fullscreen mode

It is important to also note that hoisting only works for function declaration and not function expression for this same reason.

myName()  
Function myName(){
  Console.log(“Emeka Ojukwu”
}
//Emeka Ojukwu
Enter fullscreen mode Exit fullscreen mode
myName()
var myName = function(){
 console.log(“Emeka Ojukwu”
}
//undefined
Enter fullscreen mode Exit fullscreen mode

In the first example here we called the function first before declaring it and it worked, the reason is because of hoisting, the browser declares the function before calling it. In the second example, it did not work because the function is stored in a variable and its property is initially set to undefined, calling it before declaration will give us the initial set value of undefined. That is why function declaration will work when called before declaration while function expression will not work if we call it first before declaring it.
So one difference between a function declaration and a variable declaration is the fact that the property of the variable is set to undefined while that of a function declaration is not. Hoisting does not work for const and let so trying to assess it before defining it will give you a ref error.

b. Creation of Scope

So far we have seen that scope simply means a mechanism that tells us how a piece of code can be assessed from the code base, from where and by what.
FEC creates its scope, this is an environment where the functions and all the variables it defined can be assess
In the case of a nested function in which a function is inside another function, the daughter function has access to the variable declared in its parent function and that of the global scope. This is called lexical scoping. Let us look at the following example

Image description

From the above example, we can see that the second function is nested inside the first function. When the first function is called, the browser tries to execute it only to find another function call inside, second(), it enters it to execute it, and it realises that there are three variables here, a, b and c. The browser first checks the VO2 scope for the variables, it finds only c, it then moves to the VO1 scope to search for the other variable, it finds b, then it will move to the next which in this case is the global scope, there it will find the variable. So the browser travels from the point of invocation to the global scope up the scope of an execution context, this is called the scope chain. So scope chain is actually from the point of invocation to the global scope and not the other way around.

c. Set the value of the “this” keyword

The "this" keyword refers to the scope to which an execution context belongs. In the global execution context, this refers to the global object which is the window object. Let us take a look at this example

var   Car  =  “Innoson”
  function addOne(x){
       console.log(x + 1)
   }
Enter fullscreen mode Exit fullscreen mode

This is the same as

 window.Car  = “Innoson”
  window.addOne(x){
       console.log(x + 1)
   }
Enter fullscreen mode Exit fullscreen mode

It is important to note that the FEC does not create its own “this” keyword, rather it gets access to that of the environment in which it is defined in

 var msg  = “My name is Igwebuike”
 function printMsg(){
     console.log(this.msg)
}
printMsg() // My name is igwebuike
Enter fullscreen mode Exit fullscreen mode

The "this" invoked in the printMsg function can access the msg variable because it points to the GEC of which the printMsg function has access.
In the object, unlike the function the “this” keyword does not point to the GEC but to the object itself

 var  msg  = “My name is igwebuike”
  const Car  = {
  msg  = “Am the man”
  printMsg(){console.log(this.msg)}
}
Car.printMsg()//Am the man
Enter fullscreen mode Exit fullscreen mode

This is because the printMsg function has access to the object and not the GEC

Execution Phase

After the creation phase comes the execution. It is at this point that the JavaScript engine runs through the code in the EC, and changes the value of the variable object from undefined to its actual value. The code is passed by a parser which transpiles the code to executable bytes and then gets executed.

Conclusion

Am sure you have learnt something in this article. Remember

  • Scope is a set of rules that determines how a variable is assessed

  • Execution Context, EC is the environment that contains the codes to be executed and all that is needed for the code to be executed

  • There are two types of EC, global execution context, GEC and function execution context, FEC

  • GEC creates its own this keyword while FEC do not

  • Hoisting is the reason why we can call a function declared using the var keyword as the property of the variable object is not set to undefined unlike that of a variable whose property is set to undefined. This is the same reason why we cannot call a function expression before it is defined because it is stored in a variable so the browser sees it as a variable

  • The "this" keyword is simply a link that connects a function to its execution context.

  • Scope and execution context are two factors that determine what a function can assess and what it cannot.

  • Scope chain refers to the movement of the browser from the point where the function is invoked to the global scope. It cannot move in the opposite direction.

Top comments (0)