Inside the Engine: Understanding JavaScript's Execution Mechanism

Introduction

Ever wondered what happens behind the scenes when you hit that "Run" button on your JavaScript code? Well, get ready for a backstage pass because we're about to unveil the secrets of how JavaScript really works

Think of JavaScript like the wizard of web development. It makes things happen on your screen, but how does it do it? That's what we're here to explore. In simple terms, we'll break down the steps from reading your code to making it come alive.

JavaScript Engine Basics

  • What's a JavaScript Engine?

    A JavaScript engine is the software that executes your JavaScript code. Each browser has its own engine, with V8 (Chrome and Node.js), SpiderMonkey (Firefox), and JavaScriptCore (Safari) being among the most notable.

  • The Compilation Journey: Execution Context

    Everything in JS happens inside the execution context. Imagine a sealed-off container inside which JS runs. It is an abstract concept that hold info about the env. within the current code is being executed.

  • In JavaScript the code execution is divided into two phases. One is Memory component (parsing phase) and the other one is Code component (execution phase).

  • Memory component has all the variables and functions in key value pairs. It is also called Variable environment.

  • Code component is the place where code is executed one line at a time. It is also called the Thread of Execution.

  • JS is a synchronous, single-threaded language.

  • Synchronous:- In a specific synchronous order.

  • Single-threaded:- One command at a time.

How JS is executed & Call Stack

Ever heard of the call stack? It's like a to-do list for the engine. When a function is called, it gets added to the stack, and when it's done, it's removed. This ensures tasks are handled in the right order.

Let us Understand what is Execution Stack or Call Stack with the above example:

  • When a JS program is ran, a global execution context is created and pushed into the Call Stack.

  • The execution context is created in two phases.

  • Memory creation phase - JS will allocate memory to variables and functions.

  • Code execution phase

The first thing which JS does is memory creation phase. so, it starts from the line one and sees the variable name and allocates space to it. And then goes to the second line and allocates a memory space for the function first , after that it can't go directly into the third line because it hasn't been called yet. So it moves forward and detects the functions second and third likewise and allocates space for them.

When allocating memory for variables, like here in the above example name , it stores undefined as the initial value (special value). For functions, in the above examples first, second and third , it stores the whole code of the functions in the memory space as its initial value.

The main takeaway from this parsing phase is JS allocates some initial values for all the variables and the functions described in the code.

Now, in the 2nd phase, i.e. Code execution phase, It starts going through the whole code line by line again. As it detects the variable name = "John" , it assigns the value "John" to variable name . Now coming to function first there is nothing to execute as it hasn't been called yet. It goes same with the other functions too.(second and third).

Now, coming to last line, we encounters the function calling method first() . Here the functions acts a bit different in JavaScript. Now a new Execution context is created altogether for function first and it pushes to the call stack as we can observe in the above image (execution context first).

In the above Image, we can see the flow of code execution. Now, in the first execution context after the memory creation phase, the code execution phase starts. In the code execution phase, it detects the function calling method second() and created a new altogether execution context (execution context second) in the call stack.

After that the parsing phase starts for the second() function and the variables are allocated a memory space as undefined values. In the code execution phase, It detects the function calling method third() . Again it creates a new execution context (execution context third) in the call stack.

Now in the third execution context, parsing phase starts and the memory component starts allocating memory space to the variables and functions if available. After that in the code execution phase, it allocated the actual values to the respected variables.

In our above code example there are no return statements and console.log for the output. If JS detects the return keyword while executing it stops the function execution and returns its value. if there is no value explicitly returned by the user, it automatically returns undefined. Now after the execution is done, the function execution context is deleted and pops out of the Call Stack.

Now, the third execution context is deleted, it comes to the second execution context and performs execution and return the values if any. After that it also gets deleted from the Call Stack. And the same applies to the first execution context.

After executing all the functions and variables, the global execution context gets deleted as there is node code to execute.

  • Javascript manages code execution context creation and deletion with the the help of Call Stack.

  • Call Stack is a mechanism to keep track of its place in script that calls multiple function.

  • Call Stack maintains the order of execution of execution contexts. It is also known as Program Stack, Control Stack, Runtime stack, Machine Stack, Execution context stack.

And there you have it—the backstage magic of JavaScript, where execution contexts take the lead. Think of execution contexts like the director's script, telling your code how to perform.

In simple terms, an execution context is where your code does its thing. It keeps track of what's happening, who's involved, and makes sure everything runs smoothly.

Understanding this backstage magic gives you superpowers as a coder. You can write better code, fix problems like a pro, and truly appreciate the beauty of JavaScript.

Happy Coding!