How Functions Work in JavaScript and Variable Environment:

In this blog post, we will learn about how functions work, what the variable environment is, and how the call stack handles function invocation. We will use an example to understand how this piece of code is executed.

Let's go through the example:

index.js

var x = 10; // Line 1
a(); // Line 2
b(); // Line 3

function a() {
  var x = 10; // Line 4 
  console.log(x); // Line 5
}

function b() {
  var x = 100; // Line 6
  console.log(x); // Line 7
}

console.log(x); // Line 8

As soon as we run a JavaScript program, the global execution context will be created. The execution context has two phases: the memory creation phase and the code execution phase. JavaScript won't execute a single line of code before assigning memory to all variables and functions. We also need to understand the call stack. As soon as the global execution context is created, it will be pushed into the call stack.
Picture of the call stack at this moment:

|           |
|           |
|           |
|           |
|           |
|___________|
|           |
|           |
|___________|
|           |
|   GEC     |  // Global execution context pushed into the call stack 
|___________|

Memory creation picture at this moment:

{
    x : undefined, // For variables, the default value is undefined
    a : function a(){   // entire function code will be copied  
         var x = 10;    
        console.log(x); 
    },
    b:function b(){ // entire function code will be copied  
         var x = 100;    
        console.log(x);  
    }
}

Now we are done with the memory creation phase, and you can see where all these variables are located. The memory creation phase is also known as the variable environment. As soon as the memory creation phase is done, JavaScript will start the code execution phase.

In line 1, we assigned the value 10 to the variable x, so JavaScript will replace the default undefined value of that variable and assign this new value. The execution will then move to line 2, where we invoke the function a(). As soon as this function is invoked, the execution context will be created, and it will have a memory creation phase and a code execution phase. However, it's important to understand that this execution context is specific to the current function and has nothing to do with the global execution context.

Memory creation phase for function a():
{
    x : undefined
}

In this case, we have the variable x in the global execution context, but the x above has nothing to do with it because we created a new variable x inside the function and assigned a new value to it. So it will get its memory. We invoked the function a(), so it will also be pushed to the stack. At this time, the picture of the stack will be like this.

|           |
|           |
|           |
|           |
|           |
|___________|
|           |
|    a()    | // Function a() got invoked and pushed into the call  
|___________|
|           |
|   GEC     | // Global execution context pushed into the call 
|___________|

Now inside function a() on line number 4 we are assigning the value 10 to variable x so it will remove the default undefined value and will assign the value 10 to x. So now in line 5, we are printing the value of x here we can learn one incredible thing like which value of x should be printed we have a value of x 1 in the global execution context and we have a value of x 10 in the local execution context and ans is it will print 10 because a() has variable x inside that then why would it look for that outside it. And here we are done with function a() we executed all the lines now what. As soon as the function is done with its work it will be popped out from Call Stack. So the picture of the call stack at this moment will be as below.

|           |
|           |
|           |
|           |
|           |
|___________|
|           |
|           |  // Function a() hai nhi function a() tha
|___________|
|           |
|   GEC     |  // Global execution context pushed into call stack
|___________|

And now code will be moved to the next line which is line number 3 where we are invoking function b() so again execution context of this function will be created and it will be pushed to Call Stack. So the picture of the call stack at this moment will be as below.

|           |
|           |
|           |
|           |
|           |
|___________|
|           |
|     b()   |  // Function b() got invoked and pushed into call stack
|___________|
|           |
|   GEC     |  // Global execution context pushed into call stack
|___________|

For function b() same memory creation phase and code execution phase will happen and at the time of code execution we are assigning a value 100 to x so in the next line we are printing it so it will print 100 and now the function has no more code to execute so it will be popped out from the stack. So the picture of the call stack at this moment will be as below.

|           |
|           |
|           |
|           |
|           |
|___________|
|           |
|           |  // Function b() hai nhi function b() tha
|___________|
|           |
|   GEC     |  // Global execution context pushed into call stack
|___________|

In the last line, number 8 from the global execution context will be executed and we are doing like console.log(x) and the value of x in the global execution context is 1 so it will print 1 and that's it now Global execution context is also done with its work it will be also popped out from Call Stack. So the final picture of the call stack will be.

|           |
|           |
|           |
|           |
|           |
|___________|
|           |
|           |      
|___________|
|           |
|           |     // Call stack be like i have nothing to lose now.
|___________|

And yes that's how the execution of code happens in javascript we seen that how the control of code went from GEC to function a() and as soon as function a() was done with its work control went back to GEC and again GEC invoked function b() so control went to function b() and once b() function was done then again control went back to GEC and finally once GEC is done that it also popped out from the stack and that's how js runs entire code.

That's all about Hoisting in Functions and Variable environments. And thanks to Akshay Saini for creating an incredible Namaste Javascript playlist this blog is just whatever learning I had from there.