Understanding JavaScript Execution Context like never before

Subscribe to my newsletter and never miss my upcoming articles

Introduction

Execution Context is the most fundamental part of JavaScript programming language. In this post, we will take an in-depth dive into this concept to find out, it is not only fundamental but, extremely easy to understand.

In many of the cases, the concept of Execution Context has been projected as an Advanced JavaScript Concept from the understanding and the complexity of the learning perspective. Yes, this may sound complex to one if not learned with proper examples in the correct sequence. Along with it, every beginner to JavaScript need to understand, why is it important to gain confidence in this fundamental concept?

This is the second post of the series called, JavaScript: Cracking the Nuts. If you haven't read the first post about JavaScript Interpreted or Compiled, please give it a try. Hope you enjoy reading it.

If you haven't read the previous post of the series yet, you can find it here: JavaScript Interpreted or Compiled? The Debate is Over.

Why is this concept Important?

Some study says, The human brain may be able to hold as much information in its memory as is contained on the entire Internet! But we shouldn't take that for granted, right? Hence a valid question could be, Why is this concept Important to Learn?

JavaScript's Execution Context is the base to understand many other fundamental concepts correctly. Often we find lots of misunderstanding in each of the following concepts just because, we misunderstood the fact behind Execution Context.

  • Hoisting
  • Scope
  • Scope Chain
  • Closure
  • Event Loop

As a JavaScript Developer, once we develop a good understanding of these concepts, we enable ourselves to,

  • 🐛 Introduce lesser bugs into the Source Code.
  • 👩‍🏫 Become a boss in doing great Code Reviews.
  • 👀 Great eyes for Debugging.
  • 🏭 Easier ways to tackle Production Issues.

Do not be Overwhelmed

A word of encouragement, Don't be Overwhelmed if you are new to this.

overwhelmed.gif Taken from https://giphy.com/

I am not sure why, but most of the programming languages are full of heavy Jargons that could be discouraging at times. The underlying concepts behind those Heavy Words are mostly simpler and easy to grasp. Here are a few that are useful for this post:

  • Parser: Parser or Syntax Parser is a program to read your code line-by-line and understand how it fits the grammar defined by the Programming Language and what it is expecting to do. As you have seen in my previous post, the JavaScript Syntax Parser takes the array of tokens and create an Abstract Syntax Tree(AST) so that, it can be processed further to create executable code.
  • Lexical Environment: The word Lexical means, relating to the words or vocabulary of a language. Lexical Environment means, how and where your code physically is written. Let's take this piece of code as an example,

     function sayName() {
      var name = 'someName';
      console.log('The name is, ', name);
     }
    

    In the code above, the variable name is lexically inside the function sayName. Now, this is important to note, your program doesn't run as-is on Computer. It has to be translated by the Compiler. Hence it has to correctly know and map what is lexically sitting where so that, the compiled output is also meaningful and valid.

    Please note, usually, there will be many Lexical Environment in your code. But all the environments will not be executed at once. We will see that shortly.

  • Context: The best way to visualize the word Context is, think of a circle(or Wrapper) surrounding the topic of your interest(or the 'Context of' what we are discussing). Context is a set of circumstances or facts that surround a particular event, situation, etc.
  • Execution Context: It means, the code that is currently running and everything surrounding to that is helping in running it. There can be lots of Lexical Environment available but, the one Currently running is managed by Execution Context.

    Here is a pictorial demonstration to explain the same,

    lexical.gif Lexical Environment vs Execution Context

Execution Context

As Software Developers, we like(or wish) to write code in such a way that, it looks less complex, can be maintained easily, and follows some practices, standards, etc. With the same analogy, the Execution Context allows the JavaScript engine to maintain the code and manage the complexities in better ways.

Whenever a code is run in JavaScript, it runs within the Execution Context which is a combination of your code plus, all that we have seen here (Tokenizing, Parsing, Code Generation, etc) done by JavaScript Engine.

Global Execution Context(GEC)

Whenever a JavaScript Code first runs, it creates something called, Global Execution Context(GEC). Even when you do not have a single line of code in a .js file and load it, you will have the Global Execution Context created.

What does the word Global mean here? Anything and Everything Outside a Function is Global.

Global Execution Context is also called a base execution context. It creates two special things for you,

  • A global object called, Window object for browser. If you are using JavaScript at the server side, say, nodeJs, it will not be Window.
  • A global variable called, this.

Let us understand Global Execution Context with couple of examples,

Loading an Empty Script

For the sake of simplicity, takes an empty JavaScript file called, index.js and import it in a html file called, index.html like this,

<html>
   <head>
     <script src="index.js" />
   </head>

   <body>
     I load an empty Script
   </body>
</html>

Once you load this HTML on the browser, there will not be any JavaScript loaded and executed but, if you open the debugger console(F12 for Chrome) and type this,

this.png

You see there is something called this has been created for you already. You can also try typing Window, this time you will have the Window object printed,

window.png

Have you noticed, the Window object and the this variable both are equal in the Global Execution Context? Try this to confirm,

this_equal_true.png

A Global Execution Context when it is just created without any JavaScript code can be visualized as,

gec.png Created using tylermcginnis.com/javascript-visualizer

With Variables and Functions

Let us add some code to our js file now. We have added a variable called, name and initialized with the value, Tom. We also have a function called, sayName() which just logs the name.

var name = 'Tom';

function sayName() {
  console.log(this.name); 
}

What do you think will happen to the Global Execution Context now? Let us see it in the following pictorial demonstration first and then the explanation follows.

creation_execution_1.gif Global Execution Context Phases

  • There are two phases created in Global Execution Context, i.e Creation phase, and Execution phase.
  • Creation Phase:
    • In this phase, two special things get created, i.e, a global object like Window for browser and a variable called, this.
    • Memory gets allocated for the variable name and the function sayName().
    • The variable name gets initialized by a special value called, undefined. The function sayName() gets placed directly into the memory. We will see more about it in the upcoming post about another concept called, hoisting.
  • Execution Phase:
    • In this phase, the code actually starts getting executed. For our example above, the only thing to happen is, it will assign the value Tom to the variable name. Please note, we do not invoke the function sayName() though we have defined it. Hence this function will not get executed. We will see about Function Execution in the next section.

Function Execution Context(FEC)

A Function Execution Context gets created when a function is invoked.

Let us see the following example to understand this concept. In this example, we have a global variable called, name which is assigned a value called, Tom. We have a function called tom() which logs the name. At last, we invoke the function tom().

var name = 'Tom';
function tom() {
   console.log(this.name + ' Runs');
}
// Invoke the function tom()
tom();

See the following demonstration to understand the Function Execution Context and Global Execution Context together.

context_new.gif Created using tylermcginnis.com/javascript-visualizer

  • As we have seen above, Global Execution Context's Creation phase creates the global object, this variable, creates a memory for the variable and the function. The variable gets initialized with a special value called, undefined.
  • In the Execution phase, it assigns the value to the variable and invokes the function. Hence a Function Execution Context gets created.
  • The Function Execution Context goes through the same phases, Creation and Execution. An important point to note, the Function Execution Context has access to a special variable called, arguments which is the arguments passed to the function while invoking. In our example, we do not pass any arguments. Hence the length is 0.
  • A function can invoke another function and it can invoke another and so on. For each of the function invocations, there will be a Function Execution Context get created. We will see this concept in detail with the upcoming post on Scope.

So, what are the differences between Global and Function Execution Context?

Global Execution ContextFunction Execution Context
Creates a Global object.Doesn't create the global object. It creates an argument object.
Create an object called, thisBy default, this points to Window object(There are lots more to it, we will see in future posts).
Setup memory space for variables and functions defined globallySetup memory space for variables and functions defined within the function.
Assign variable declaration a default value of undefined while placing any function declaration in memoryAssign variable declaration a default value of undefined while placing any function declaration in memory. Additionally, the function execution context creates its own Execution Stack.

Conclusion

The Global and Function execution Context and the phases(Create and Execute) are important concepts to get used to. This will help in understanding Scope, Asynchronous Functions, Closure, Hoisting, etc with ease. We will be seeing each of the concepts in detail in the upcoming post of the series.

If you are new to the concept of the execution context, use the JavaScript Visualizer Tool side-by-side while learning this concept. Write small functions, user-defined variables, execute functions, and see how the tool takes it through various phases of the execution contexts.


If it was useful to you, please Like/Share so that, it reaches others as well. To get e-mail notification on my latest posts, please subscribe to my blog by hitting the Subscribe button at the top of the page.

This story has been translated into Russian and published here as well.

In the next post of the series, I'll be explaining about another fundamental concept called, Hoisting. Stay Tuned.

Rahul's photo

This is the freaking best series. Loved it so much.

Show +1 replies
Rahul's photo

i was just seeing my old rfa request and now I am reading your amazing articles. Super best againi.Tapas Adhikary

Tapas Adhikary's photo

Rahul that's awesome, very glad... and tons of thanks 🙏.

Feel free to share for others to use it 👍

Jome Favourite's photo

Very well explained. Thanks for the series.

Tapas Adhikary's photo

Thank you for reading and taking the time to comment, appreciate Jome Favourite.

Jome Favourite's photo

You're welcome, I'm looking forward to learning more advanced concept in Javascript Tapas Adhikary