How JavaScript Works Behind The Scenes

Deep Dive Into Javascript

November 16, 2022

What is Javascript? Javascript is a High-Level, Prototype-Based Object-Oriented, Multi-Paradigm, Interpreted or Just-In-Time Compiled, Dynamic, Single-Threaded, Garbage-Collected Programming Language…Wait, what?!

Okay, let’s take a step back. JavaScript is a programming (or scripting) language that allows you to implement complex features on web pages. But how is it doing all these things? In this article we’ll go through everything that happens behind the scenes in Javascript. Having an understanding of this topic will allow us to better understand our code and see the big picture (also it's a very interesting concept to learn). Without further ado, Let’s begin.

The Javascript Engine

Javascript Engine is simply a program that executes Javascript code. It compiles the source code to the machine code that a CPU can understand. Every browser has its own JavaScript engine, but one of the most famous JavaScript engines is Chrome V8 engine. Microsoft Edge also switched to Blink browser engine with V8 JS engine. The others are SpiderMonkey for Mozilla Firefox and JavaScriptCore for Safari.

The JavaScript engine consists of 2 components:

  • Call Stack: That’s where our code is executed by using Execution Context. This is a mechanism for an interpreter to keep track of its position in a script that calls several functions.
  • Heap: It’s an unstructured memory pod which stores all the objects that our app requires.
Javascript Engine

Execution Context

Execution Context (EC) is simply an abstract concept of an environment in which the Javascript code is executed. It contains the code that is currently running.

There are 3 types of Execution Context in Javascript:

  1. Global Execution Context (GEC): This is the default EC where all javascript code that is not inside of a function gets executed. For every Javascript file there can only be 1 GEC.
  2. Functional Execution Context (FEC): Whenever a function is called, the Javascript engine creates FEC within GEC to evaluate and execute the code within that function. There can be more than one FEC.
  3. Eval: Execution context inside eval function

How are Execution Contexts Created

Now let’s look at how they are created. Creation of an Execution Context happens in 2 phases:

  1. Creation Phase
  2. Execution Phase

Creation Phase: It happens in 3 stages:

  1. Creation of the Variable Object (VO)
    1. let, const and var declarations
    2. Functions
    3. arguments object
  2. Creation of the Scope Chain
  3. Setting the value of this keyword

Execution Phase: After the creation phase of an Execution Context comes the execution phase. This is the stage where the execution of our code begins. At this stage, JS engine updates the Variable Object with the actual values. Then the code is parsed by a parser, and finally gets executed.

Let’s see how this piece of code gets executed:

Execution Phase

As we can see here, we get one Global Execution Context and two Functional Execution Contexts.

And now let’s finally see the Call Stack:

Execution Phase

Step 1: GEC is created and this is the place where all the code outside of functions will be executed. Here we have text variable, sum and multiply functions declarations.

Step 2: This step starts when we call the sum function and now it’s the current execution context.

Step 3: In sum, we call multiply and a new execution context gets created. Then it gets pushed to the Call Stack. One thing to note here is that since Javascript runtime is Single-Threaded, it can only do one thing at a time. So the sum function pauses at this point and we only execute the multiply function.

Step 4: When the multiply function returns the result, the respective EC has been removed from the stack. Here we continue to execute the sum function.

Step 5: sum returns the result and as we already know it gets popped out from the stack. The program will stay in this phase until it really finishes. And it will only happen if we close the browser tab or the window.

Step 6: Finished.

Javascript Concurrency Model & Event Loop

Now we have an understanding of how our code is executed. And let’s take this one step further and understand the Concurrency and Event Loop in Javascript.

Javascript runtime is Single-Threaded. This means it maintains a Call Stack and a Memory Heap. It can only execute one thing at a time (see Step 3). If we have too many functions to run in the Call Stack, the browser is stuck and can do nothing.

Let’s see this code below:

Code block

One may expect it to be First, Second, Third. But we have an asynchronous function here. This process is different than the regular one.

And now let’s observe the Call Stack for this operation:

Execution Phase

Step 1: Logs the First.

Step 2: console.log doesn’t run immediately, it’s going to run in 3 seconds. We can’t push it up to the stack so it pops out. (We will talk about where it goes)

Step 3: Logs the Third.

Step 4: Everything is finished.

Step 5: But wait, it logs the Second.

This is where the Concurrency and Event Loop comes into play. We already said that Javascript runtime is Single-Threaded but the browser is more than just a runtime. That’s the reason we can do things concurrently.

Here is the bigger picture:

Execution Phase

Web APIs

When the Javascript engine detects an asynchronous function, it sends it to the Web APIs. Here the asynchronous function waits to resolve. In Step 2 above we saw that the setTimeout function has been sent to the Web APIs. After the resolution in Step 5 we received a console.log.

Callback queue

This is the place where all the asynchronous functions go. It follows the First In First Out (FIFO) order. Our setTimeout function is pushed here when it’s ready for execution.

Event Loop

The main purpose of Event Loop is to check the Call Stack. If it’s empty it pushes the first processed function from the Callback queue.

Let us now take a broader view of the same process:

Step 1: Logs the First.

Step 1

Step 2: As we remember from above, console.log doesn’t appear immediately. Browser starts the timer and pushes the callback to the Web APIs. Also removed from the stack.

Step 2

Step 3: Logs the Third.

Step 3

Step 4: 3 seconds later our function is ready for execution. That’s why it moves to the Callback queue now.

Step 4

Step 5: Logs the Second.

Step 5

Step 6: Done.

Step 6

Conclusion

This article covers the aspects of how JavaScript works behind the scenes. This is the basis for understanding many other basic concepts properly. I hope now that you have a better understanding in what order your functions/code works and how JavaScript Engine handles them.

Hope you found this article helpful. Thank you for your time and happy coding!


Engineering Goodies

Zaur Ibrahimov
Personal blog by Zaur IbrahimovThings that interest me