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.
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.
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.
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.
Create a boilerplate HTML file and an empty javascript file and link them.
Link the HTML file to an empty javascript file (as done on line 13)
Open the HTML file in a browser and open up the console in the dev tools.
Type window in the console
window is the browser’s global object which gets created anytime a javascript file runs (Node and other javascript runtime environments have different Global Objects).
Let’s now look at the keyword ‘this’. Type this in the console Notice, ‘this’ is the same as the browser’s Global Object - window, i.e. ‘this’ is a reference to the window object. So, anytime the Global execution context is created, a global object (window, in the case of the browser) is created, and its reference is passed to ‘this’.
You can look at the Node’s global object by opening a Node REPL and typing ‘this’
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.
Let’s finally write some code in our javascript file and understand the creation and execution phases.
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.
We get the expected output -
Now, let’s change our code a bit.
We made the following changes -
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,
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, **
Let’s run our code and look at the output in the console:
Let’s understand what happened here -
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).
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**.
Variables declared with let and const are not hoisted.
Let’s declare our variable int with let and see the output.
When we run the code we get the error:
As mentioned above, this is because let and const are not hoisted. We will learn about Hoisting in detail in another post.
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.