How do the Execution Context, Call stack, and Event-loop work in"JavaScript?

How do the Execution Context, Call stack, and Event-loop work in"JavaScript?

JavaScript is a high-level, dynamic, and interpreted programming language. It was created to add interactivity to websites, but it has since evolved into a language that can be used for many applications.

The JavaScript engine is responsible for executing JavaScript code. The engine starts by parsing the code into a series of instructions known as "bytecode." The machine executes the bytecode, which interprets the instructions and carries out the actions specified by the code.

Execution Context

Every time JavaScript code is executed, an "Execution Context" is created. An Execution Context is a unique environment created by the JavaScript engine to complete a single piece of code. It determines the value of this keyword, the variables in scope, and the memory allocation for the code being executed.

The JavaScript engine keeps track of all the Execution Contexts in a stack-like structure, where the context at the top of the stack is the one currently being executed. As the engine encounters function calls, it creates a new Execution Context for the called function and pushes it onto the top of the stack. When the process returns, its Execution Context is popped from the stack, and the engine resumes execution of the previous context.

Every time a variable or function is declared, it is added to the current Execution Context's "Variable Object." The Variable Object holds all of the variables and functions defined in the current context and is used to resolve variable references.

In addition to creating a new Execution Context for function calls, the JavaScript engine also creates a new Execution Context for every new block of code executed, such as an if statement or a for loop. These block-level Execution Contexts have their Variable Object, and they create a new scope for the variables declared within them.

The concept of scope in JavaScript is essential to understand because it determines the accessibility of variables. Variables declared within a function have local scope, meaning they are only accessible within that function. Variables declared with the var keyword have function scope, accessible within the process and any nested functions. Variables declared with the let, and const keywords have block scope, meaning they are only accessible within the block in which they were declared.

Once the engine has finished executing a piece of code, it cleans up the associated Execution Context, freeing up memory and removing it from the stack.

In summary, the JavaScript engine executes code by parsing it into bytecode, creating an Execution Context to execute the code, keeping track of all Execution Contexts in a stack-like structure, and using the Variable Object to resolve variable references. The engine also creates new Execution Contexts for function calls and block-level code, and it cleans up Execution Contexts once the code has been executed.

Call Stack

The Call Stack is a data structure that keeps track of the function calls in JavaScript. It operates on the "Last In, First Out" (LIFO) principle, meaning that the last function that was called will be the first one to be executed.

Every time a function is called in JavaScript, it is pushed onto the top of the call stack. The function then starts to execute, and when it's finished, it is popped off the top of the stack. If a function calls multiple other functions, those functions will be pushed onto the stack in the order they are called, forming a stack of function calls. The JavaScript engine will continue to execute functions in the order they were called until the stack is empty.

Let's take a look at an example to see how the call stack works:

function multiply(num1, num2) {
  return num1 * num2;
}

function square(num) {
  return multiply(num, num);
}

function printSquare(num) {
  console.log(square(num));
}

printSquare(2);

Let's take a look at an example to see how the call stack works:

In this example, when printSquare(2) is called, it is pushed onto the top of the call stack. The function then calls square(2), which is pushed onto the top of the stack. The square function then calls multiply(2, 2), which is pushed onto the top of the stack. The multiply function executes and returns 4, which is then popped off the top of the stack. The square function, which received the result of the multiply function, also executes and returns 4, which is then popped off the top of the stack. Finally, the printSquare function, which received the result of the square function, executes and logs 4 to the console, which is then popped off the top of the stack.

Event Loop

As I mentioned earlier, JavaScript is a single-threaded programming language that can only process one task at a time. However, it needs to handle multiple tasks, such as responding to user input, updating the UI, and making network requests. To handle these tasks, JavaScript has a mechanism called the "Event Loop."

The Event Loop is a continuous loop that monitors the call stack and the task queue. The task queue is a list of tasks waiting to be executed. When the call stack is empty, the event loop will take the first task from the task queue and push it onto the call stack. The task will then be executed. When the task is finished, and the call stack is empty again, the event loop will take the next task from the task queue and repeat the process.

This mechanism ensures that JavaScript can handle multiple tasks asynchronously, allowing it to respond to user input, update the UI, and perform other tasks without blocking the main thread. For example, when a user clicks a button on a page, an event is added to the task queue. The event loop will eventually pick up the event and push it onto the call stack, where it will be executed.

One important thing to note is that JavaScript uses what is known as a "Microtask Queue" for executing microtasks, such as process.nextTick and Promise callbacks. Microtasks are given priority over tasks in the task queue, so they are executed before any other tasks in the task queue.

In summary, the Call Stack and Event Loop work together to allow JavaScript to execute multiple tasks in a single-threaded environment. The Call Stack keeps track of function calls, and the Event Loop monitors the call stack and the task queue, ensuring that tasks are executed in an orderly and predictable manner. The Event Loop takes tasks from the task queue and pushes them onto the call stack for execution, and when the call stack is empty, it takes the next task from the task queue and repeats the process. This mechanism enables JavaScript to handle multiple tasks asynchronously, allowing it to respond to user input, update the UI, and perform other tasks without blocking the main thread. The Microtask Queue also ensures that microtasks, such as process.nextTick and Promise callbacks, are given priority over tasks in the task queue and are executed before any other functions in the task queue.

That's all, folks

These are crucial topics you should know to understand how JS code works.

KNow more stuff, share more knowledge

Let's Rock!!!

Did you find this article valuable?

Support PRAVEEN ALLURI by becoming a sponsor. Any amount is appreciated!