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.
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:
- 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.
- 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.
- 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:
- Creation Phase
- Execution Phase
Creation Phase: It happens in 3 stages:
-
Creation of the Variable Object (VO)
let
,const
andvar
declarations- Functions
arguments
object
- Creation of the Scope Chain
-
Setting the value of
this
keyword
arguments
object and 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:
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:
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:
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:
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:
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 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 3: Logs the Third
.
Step 4: 3 seconds later our function is ready for execution. That’s why it moves to the Callback queue now.
Step 5: Logs the Second
.
Step 6: Done.
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!