JavaScript under the hood: Execution Context
Discover how magic happens inside a JavaScript Engine!

Every time you start a JavaScript project probably you follow most of these common steps:

  • Setup you the project with a package manager like npm or Yarn
  • Add a bundler that could be webpack, rollup.js, or any other. As alternative you can use a more aged task runner like Grunt or Gulp, or even a mix of them.
  • Develop your source code
  • build your project (this simply means generate the final JS code)
  • and finally... see the result on a web page


There is another important step that is missing and happens behind-the-scenes...

have you ever wonder what happens inside the browser since when the JavaScript file is received to its execution?

#Javascript Engine

The first and most important character in this story is the JavaScript Engine.

But, what is it?

JavaScript Engine is the program that take the JavaScript code and execute it.


Saying “execute it” it’s not exactly what happens. We usually think at JavaScript as an interpreted language rather than a compiled language. That was true in the past but nowadays things are more complicated and deserve a deeper explanation. For now we can say that:

Javascript Engine compiles the code line-by-line just before it is being executed and we call it just-in-time compilation

Now, if you want to understand JS engine behaviour you need to start thinking like a JavaScript Engine.

Suppose that you web page contains only this simple script:

const jedi = "Luke";
let jediList = ["Luke", "yoda", "Obi-Wan"];
const defaultJediList = ["Luke", "yoda", "Obi-Wan"];
const message = "Use the force";

function useTheForce(character) {
  const otherJediList = ["Mace Windu", "Kit Fisto"];
  let jediList = [ ...defaultJediList, ...otherJediList ];

  if (jediList.includes(character)) {
    console.log("%s %s !", message, character);
    // => "Use the force Luke!"

#Execution context

If you were a JS Engine the first thing you do is to prepare a comfortable environment to host the incoming code. This environment is named execution Context (EC) and we can simply define it as

the environment where JavaScript code is executed

To make this concept more pragmatic we can say that it contains all the information necessary for code execution, this includes the this reference, and all the variables, objects and functions definitions).

Now, what happens at page loading is that a default EC is created with the name of Global execution context.

It contains all the the built-in variables and functions of the language like the properties Math, String, console , or window (that is a reference itself to the Global Object).

Back to our code, and remember to think like a JS Engine. How would you read the above script?

As we already know, the answer is line by line, top to bottom.

**Line 1** - Engine: I see a constant declaration, I store it

**Line 2 **- Engine: I see a variable declaration, I store it

**Line 3 **- Engine: I see a constant declaration, I store it

**Line 4 **- Engine: I see a variable declaration, I store it

**Line 6 **- Engine: I see a function declaration, I store it

At the end what happened is that some declarations are stored in the global memory, no code execution happens. Anyway, there is a new character in our story I would like to introduce…

Lexical Environment

When we speak about storing variable and function declarations I mean saving somewhere the association of identifiers to their values. This place is a component called Lexical Environment and it’s managed following the lexical nesting structure of the code.

More or less the behaviour is this:

  • every time a scope is found a new Lexical Environment is created
  • for each Lexical Environment there is an Environment Record that maintains the list of identifier bindings found in the current scope
  • An outer environment reference maintains a link to the external Lexical Environment (or scope).

In our code we have only the global scope, its lexical environment contains the four variable and the function declaration.

Note that for the outer environment reference is null as it doesn’t have any parent scope.

JavaScript under the hood: Execution Context

#Call stack

Our script is interesting: very clean and dry. Now I gonna make the things more complicated by adding a function call (Oh my God, now it’s very tricky!