← back

JavaScript's Execution Context

Why do we care about the Execution Context?

Execution context forms the basis of understanding critical Javascript concepts such as hoisting and scope. As such, execution context will help us understand some quirks and “weird” behaviour of JavaScript.

What is Execution Context?

Before looking at execution context in action, let’s first define what execution context is. Execution context is a wrapper containing information about the code currently being evaluated and executed. In other words, it’s the environment in which the code is executed.

Types of Execution context

This post will cover the Global Execution Context in detail as the knowledge of the Global Execution Context lays the groundwork for understanding Function execution context and the need for it.

From here on, when we mention Execution Context, we will be referring to the Global Execution Context.

Global Execution Context

When a javascript file starts running, a base execution context is created. The base execution context is called the Global execution context. When the Global execution context is created, we get access to a few things; **the Global Object **and ‘this’. Let’s look at the Global Object and ‘this’ in practice.

Phases of Execution Context

Before looking at how things change in the execution context when we write some code inside our javascript file, let’s first understand the Phases of Execution Context.

Phase 1: Creation Phase

  1. The global object is created in the creation phase (We already looked at the global object).
  2. ‘this’ is created, and it is bound to the global object.
  3. The memory heap is set up, and variables, and function declarations are stored inside the memory heap (We will come back and look at this in detail).

Phase 2: Execution Phase

  1. Code is executed line by line:

Creation phase and Execution phase in practice

Let’s finally write some code in our javascript file and understand the creation and execution phases.

e-demo-js1.png

Variable int is declared with var intentionally. We will look at ES6's let and const later.

Let’s save and run our file, and see what we get in the console.

demo.png

We get the expected output -

  1. The value of variable int is printed to the console.
  2. The log statement inside the loggerFunction is printed to the console.

Now, let’s change our code a bit.

e-demo-js2.png

We made the following changes -

  1. We are logging the variable int to the console before it is declared and initialized.
  2. We are invoking the loggerFunction before it is declared.

Before running the code, let’s understand this code inside the phases of execution code. We already know that in the creation phase, a memory heap is set up within which variables, and function declarations are stored.

Creation Phase in our code,

  1. window object is created, and its reference is set to ‘this’
  2. variable int and loggerFunction declarations are stored inside the memory heap.

In the execution phase, the code is executed line by line. In this phase, values are assigned to variables and functions are invoked.

**Execution Phase in our code, **

  1. The variable int is logged to the console (NOTE: int has not yet been assigned any value)
  2. Once the int is logged to the console, the next line assigns value to the variable int.
  3. loggerFunction is invoked.

Let’s run our code and look at the output in the console:

demo.png

Let’s understand what happened here -

  1. The value of variable int is undefined: We did not get an error for logging the variable int to the console before it was declared and initialized because during the creation phase (before even a single line is executed), the declaration of variable int was stored in the memory. The variable int is set to ‘undefined’ because it has not yet been assigned any value (assignment happens in the execution phase).

  2. The loggerFunction is invoked before it is declared: We were able to invoke the loggerFunction before it was declared because, in the creation phase, function declarations are stored in the memory, so, we had access to the loggerFunction declaration when it was invoked.

The behaviour we saw with our variable and function declaration is what we call **Hoisting**.

Let and Const are not Hoisited.

Variables declared with let and const are not hoisted.

Let’s declare our variable int with let and see the output.

e-demo-js3.png

When we run the code we get the error:

demo.png

As mentioned above, this is because let and const are not hoisted. We will learn about Hoisting in detail in another post.


globalThis

We now know that different javascript environments have different global objects. Browser’s global object is the window, which is different from Node’s global object, which might be different from other runtime environments. When a program is written for multiple environments, it becomes complicated to consistently refer to the global object of an environment. This was solved with the introduction of globalThis in ES2020. You can learn more about globalThis here.