Everything you'd ever need to know about the working of JavaScript

This is a completely comprehensive guide that will help you understand the working of JS in depth!

Everything in Javascript happens inside an "Execution Context"

Whenever you'd run a Javascript code, the first thing that will happen is the creation of an Execution Context, but what exactly is this Execution Context?

You can think of it as a large box which consists of two parts that are as follows:

  • Variable Environment: This is where all the variables and functions are stored as key-value pairs before the actual execution takes place. All the variables, including fat-arrow functions, are assigned a default value of undefined whereas, for all the traditional functions, the name of the function becomes the key and the code inside the function becomes the value.

  • Execution Thread: You can visualize this as a single large thread where the entire code of Javascript is executed line by line.

The practical working of Execution Context

Let's now understand this with an example, consider the following piece of code

var a = 2; //A normal variable

function square(num){ //A traditional function
    var res = num*num;
    return res;
}

var square2 = square(a);
var square3 = square(4);

As the code is made to execute, a Global Execution Context is created. This happens in two phases, which are as follows

  • Memory Creation Phase: In this phase, Javascript allocates the memory to all variables and functions. In our example, the first variable encountered is a and memory is allocated to it.

    • The first variable encountered is a and memory is allocated to it. the default value is undefined, which will look somewhat like this { a: undefined }.

    • Now a function is encountered, and this time the name of the function is stored as the key and the entire code inside the value, which would make our variable environment look as follows

      { a: undefined, square: "var res = num*num; return res;"}

    • Finally, the last two variables are allocated memory. Now the variable environment finally looks like this

      { a: undefined, square: "var res = num*num; return res;", square2: undefined, square: undefined}

  • Code Execution Phase: In this phase, the code is executed line by line and the following steps are observed.

    • The first piece of code we encounter is a = 2, which replaces the default value of {a: undefined} with 2 in our variable environment making it { a: 2 }

    • Now comes the interesting part, we come across a function, this results in the creation of a new execution context, which consists of its own variable environment { num: undefined, ans: undefined } and execution thread.

    • When the function is invoked, the value of the argument a in square(a) will be assigned to the variable num in the execution context which will make it as follows { num: 2, res: undefined }

    • Now the next line is executed which will first calculate num*num and assign the result to res and our final variable environment will look as { num: 2, res: 4 }

    • Now, return is encountered, which returns the control back to the context from where it was invoked. Here it's the global execution context. The value of square2 is now replaced with 4 (res)

    • There might also be cases where the function would be called within another function, in that case, the control will be returned to the function within which the inner function was called. After the transfer of control, the execution context for the function is deleted.

    • Similarly, the next invocation of the function occurs and the execution context is created, the calculations are done and the final result is assigned to square4.

    • Now the whole code is executed, and now the global execution context is deleted.

Quick Recap!

  • First, the global execution context is created

  • All the variables and functions are assigned memory and default values, which are undefined for variables and fat-arrow functions and the inner code for traditional functions.

  • The code is executed line by line, and the values of the variables are replaced as soon as the real value of the variable is encountered.

  • In the case of a function, a new execution context is created with memory for local variables and a similar process is repeated as the code inside the function is executed.

  • The control is returned to the parent execution context after the function has completed its execution.

  • After all the code is executed, the global execution context is also deleted.

I hope I was able to help you understand how the code of Javascript actually executes😊

Special thanks to Akshay Saini's playlist "Namaste JavaScript" for providing me with this knowledge, you can find his video here

KAMUI!🎎