How does Javascript work?

How does Javascript work?

Being a javascript user, you may have encountered some of the basic concepts like hoisting, closure, scope, and all. But, before we learn and understand these concepts, we need to understand the primary process that works in the background, and we always miss understanding. This concept will give you the idea of the inner working of how a Javascript code compiles and run in a web browser/node server.

So, let introduce this topic of discussion that helps in understanding the working of Javascript code.

Execution Context

Execution context is the place where actually everything inside JS executes. Every javascript code carries out in an execution context only. At the top of any javascript code, it creates an Execution context, which will be global throughout the JS code. So, before we move further, let’s see and discuss how execution context helps in the working of a Javascript code.

To understand the execution context, you can treat it as a block of context that lets the compiler know about all the variables, functions declared in that context. In simple words, the creation of execution context takes place in 2 phases-

  1. Memory creation phase
  2. Code execution phase

So, execution context can be said to set a context that first does all the fetching of variables & functions local to that context, and then does the code execution after that.

1_UQPF6rO6KVIsGRXovMVIyw.png

There is one more thing to be discussed which supports and maintains the order of the execution of execution contexts.

Call Stack

As for now, we will not cover the call stack in deep, but you can infer from its name, that it’s a stack.

Whenever the engine is asked to create a new execution context, it first pushes the execution context reference into the call stack and pops it out when the code inside the context completes. Once the execution context pops out from the call stack, that execution context gets deleted completely, with no access to that context’s variables and functions defined. There is some slight variation in the concept of closures, but right now, we will ignore closure.

So what we infer is,

  1. Call stack manages the order of execution of the execution context.
  2. With each execution context creation and deletion, the JS engine pushes and pops out it from the call stack.
  3. Global execution context automatically becomes the first context to be pushed and the last context to be popped out from the call stack.

1_Nfx4eQVGvXP1w9-YEiFchA.png

Let’s discuss the same with a simple code example,

1_YO_6Rrc-OgbrR0NxMkGWgA.png

So, in the above code snippet, it’s a simple JS code with some variables and functions defined and executed.

At the end of this section, you will get to know what actually works in the background and how the Javascript engine works.

As we have already discussed in the beginning that the JS engine at the beginning of any JS code creates a global execution context and subsequent execution context as we execute further.

Let’s see how the above code executes with each execution context:

  • At first, Global Execution Context is to be created. This first gets pushed to the call stack.

Memory Creation phase:

In the memory creation phase, all the local scope variables(in this, case the global scope), functions are recognized and thus given memory.

It will look something like this,

1_fjz4nY4EcOkbPdoy1Bzh1g.png

Variables are initially initialized undefined, while normal functions are given the complete function definition, the named function constants are initialized undefined, just like the variables are.

Code Execution phase:

Once the memory creation phase completes, we move over to the code execution phase. Here, the engine does the code running, value initialization, the function call, and all. Let’s discuss this phase for the above example.

1_GJ4LvWsEm0oLFJcMsXZOww.png

  • When the code executor reaches line 1, it sees

var a=2;

  • As it moves to line 2, it sees the function definition, and it moves further.

  • After this, it reaches line 7, where it sees value initialization of variable b.

var b=5;

  • Once it reaches line 8, here the engine sees a function call, and this leads to the creation of a new execution context local to the function called, and this context’s reference to being pushed into the call stack.

Now call stack contains two element — Global execution context and getTwiceTheNumber() execution context.

So, here we will discuss the new execution context created, with the call of function getTwiceTheNumber().

1_jxjWLVRXvr_C3NTSc3JEcA.png

Memory creation phase:

Here also, just the global context, all the local scope variables to the function will be fetched and initialized to undefined.

Code execution phase:

1_yjCoMsLFlrmlgfYda_YB0w.png

  1. So, now the engine reaches inside of the function and executes its first line of code. Here it sees -

let double = num;

It will ask the scope of the variable double is there in their local memory scope, if it exists the value num*2 (num=2) is assigned to it.

  1. Now, it will go to line 3, console.log the variable double.

  2. In line 4, it seems that there is a return statement, which also signifies the end of the function scope. It returns the value to the function call line, and here,

    • The execution context scope ends. It gets popped up from the call stack.
    • The execution context scope gets deleted.
  3. So, we are back again to line 9, which similarly calls the function getTwiceTheNumber(). Here is a new execution context is to be created as we saw in the above section. It will be pushed into the call stack and popped when completed.

  4. Once line 9 has completed execution, there will be no line of code to process more, and here the global context code execution also completes, and it gets popped out from the call stack, leaving the call stack empty.

So this is how the Javascript engine works in the background. The compiler does the variable & function memory creation. The Engine does the code execution. The scope sees the context of the variables exists or not.

This concept is the first step to understand further concepts like hoisting, closures, and all.

We will cover these concepts in some other stories.

Do give alike, if I was able to help you in any way to understand this concept. 😊