How does JavaScript work?

How does JavaScript work?

Hello, I am Shivam Verma. This is my first blog and we will try to understand the working of JavaScript today. Let's begin!!

Ever wondered how JavaScript works under the hood?

Well by the end of this blog you will have a clear understanding of that by knowing two important concepts that make it possible

  1. Execution Context
  2. Call Stack

1. Execution Context

Before diving deep into the working of JavaScript remember one thing

"Everything in JavaScript happens inside an Execution Context"

Execution Context can be thought of as an imaginary box where all the storage as well as code execution happens.

Execution Context(EC) can be classified into two main types:

  • Global Execution Context(GEC)
  • Functional Execution Context(FEC)

I will specify during further explaination that which type of Execution Context is being created at that moment, other than that we will refer to it commonly as Execution Context

So the Execution Context is divided into 2 parts

  • Memory Component
  • Code Component

The Memory Component also known as the Variable Environment allocates memory and stores variables and functions as key: value pairs.

The Code Component also known as the Thread of Execution runs through the JavaScript program and executes line by line.

Now if I may present the Execution Context visually as a diagram it can be shown as:

Group 6.png

Another line to keep in mind for working of JavaScript

" JavaScript is Synchronous Single-Threaded language "

This means that JavaScript can only execute one command at a time in a specific order. It can only go to the next line only if the current line is finished executing.

I know you might be thinking that, What about asynchronous programming in JavaScript? Is there no such concept? Did I get fooled by that tutorial on YouTube? Calm down I will write about that in upcoming blogs, let's stick to our topic for the day.

So coming back to Execution Context just remember for now that only one line at a time can be executed in JavaScript.

Let's understand the working in more detail with the help of a code example.

code_ec.png

Now when we run this code, a Global Execution Context(GEC) is created

The Execution Context is created in two phases.

  1. Memory Creation Phase
  2. Code Execution Phase

In the first phase i.e the Memory Creation Phase, JavaScript allocates memory to all the variables and functions. The JS Engine goes through the code line by line. It encounters variable declaration at line 1 and allocates memory to the variable n. Then it goes to line 2 and allocates memory for a function named square.

In the case of variable n, a special value undefined is stored with it whereas the whole function code is stored as it is in the case of the function. Coming to line 6 and 7 it encounters two more variables square2 and square4 and as they are variables assigns their value as undefined.

After completion of Memory Creation Phase the Execution Context might look like this

EC2.png

Now the second phase i.e Code Execution Phase begins The JS Engine again goes through the code line by line and executes the code. It executes the first line var n = 2 and replaces the undefined value of n from the Memory block with the actual value 2.

Then it comes to line 2 and encounters a function square and skips the code from line 2 to line 5.

Then when it goes to line 6 and encounters a function call or a function invocation. Now it knows that it has to execute a function.

" Functions are the heart of JavaScript " - Akshay Saini

Whenever a function is invoked a new Execution Context will be created and this will be a brand new Functional Execution Context(FEC) inside the Global Execution Context(GEC)

This new Execution Context will again consist of two blocks, Memory and Code, and will also follow the two phases of creation.

In its Memory Creation phase, it will allocate memory to variables and functions used in its execution.

It scans for variables and it finds num as a parameter and ans in the body and assigns undefined to them.

In the Code Execution phase the value of n which is 2 is passed to num.

Now in the function body, it executes num * num and the evaluated value is replaced for undefined in ans inside the FEC.

After execution of line 3, it encounters a return keyword on line 4, so the function knows its execution is finished and now it's time to return the control back to the Execution Context from where it was invoked which is the GEC.

While returning it returns the value of ans from its Execution Context to the Global one so the value of square2 is changed from undefined to 4.

The whole Functional Execution Context is deleted after the return of control.

A visual representation of the whole process discussed:

ECwithFEC.png

Now the control moves to line 7, where it finds another function invocation square(4) with value 4 as an argument. Again brand new FEC will be created. The whole procedure used to invoke square(n) as explained above will be repeated. The value will be evaluated and returned into square4.

If there is a function inside a function. Then a nested FEC will be created inside the FEC which is inside the GEC. This has no end it can go beyond and beyond.

After the execution of the whole program is finished, The Global Execution Context also gets deleted.

Phew, that was all about the "Execution Context", now you know how is it created and how it executes the code.

Remember I said all this nested Execution Context can go on and on, so how does JavaScript handle all this complicated nesting and control of the program. Luckily JavaScript engine has a stack to manage all these things and we call it The Call Stack, let's learn more about it in detail.

2. Call Stack

You must be familiar with the stack data structure. If not, please read it here So as we know Stack is a LIFO(Last in First Out) Data Structure. To enter data in the stack we use push and to delete we use the pop operation. The same is the working of the Call Stack in JS.

So for better understanding let us see a diagram of the working of Call Stack for the mini-program we saw earlier along with Execution Context.

CallStack.png

Initially the Call Stack is empty. The Global Execution Context is at the bottom of Call Stack. Whenever a program is run, the Call Stack is populated with the GEC.

Whenever a new function is invoked a new FEC is created and pushed into the stack. Only when it is finished executing, It is popped out of the stack.

At the end, the GEC is also popped off and the Call Stack becomes empty.

This Call Stack is used to manage all these EC's.

Call Stack maintains the order of execution of Execution Contexts

That was it. Now you know two major core concepts behind the working of JavaScript. How is code executed in JS? Now you can confidently answer that question in an interview if asked.

I learned about this stuff from an amazing Youtube Series "Namaste JavaScript" by Akshay Saini Awesome content by Akshay, visit the link and watch the videos.

Link to the videos which I followed to write this blog.

Namaste JavaScript Playlist

That's all from my side. How was it? Let me know in the comments.

If you really liked it then do share it with your friends or colleagues.

Have any doubt or want to work on a project together then follow me on Twitter and message me there. Also, comment on what should be the next topic and I will try to make that possible.