
JavaScript is a single-threaded, non-blocking, asynchronous language that uses the Event Loop to handle tasks efficiently. Understanding the Execution Context and how JavaScript manages asynchronous code is crucial for writing efficient applications.
In this blog, we will explore:
- Call Stack
- Web APIs
- Callback Queue
- Microtasks & Macrotasks
1. JavaScript Execution Context
The Execution Context is an environment where JavaScript code is executed. It consists of two main components:
- Memory Component (Variable Environment) ā Stores variables and function declarations.
- Code Component (Thread of Execution) ā Executes JavaScript code line by line.
Execution Context Lifecycle
When a function is called, JavaScript creates an Execution Context in three phases:
- Creation Phase: Memory is allocated for variables and functions.
- Execution Phase: JavaScript executes the code line by line.
- Destruction Phase: Once execution is completed, the context is removed.
2. Call Stack
The Call Stack is a data structure that keeps track of function execution. It follows the LIFO (Last In, First Out) principle.
How the Call Stack Works
- When a function is called, it is pushed onto the stack.
- Once the function execution is completed, it is popped off the stack.
- The process continues until the stack is empty.
Example:
function first() { console.log("First function"); } function second() { first(); console.log("Second function"); } second();
Call Stack Process:
second()
is pushed onto the stack.- Inside
second()
,first()
is called and pushed onto the stack. first()
executes and is popped off the stack.second()
continues execution and is then popped off the stack.
3. Web APIs
JavaScript interacts with the Web APIs provided by the browser (like setTimeout
, fetch
, DOM manipulations, etc.) to handle asynchronous tasks.
Example of a Web API function:
console.log("Start"); setTimeout(() => { console.log("Inside setTimeout"); }, 2000); console.log("End");
Execution Process:
console.log("Start")
runs immediately.setTimeout
is sent to the Web API, which starts a timer.console.log("End")
executes while the timer runs in the background.- After 2 seconds, the callback function is moved to the Callback Queue.
- The Event Loop picks the task from the queue when the Call Stack is empty.
4. Callback Queue & Event Loop
The Callback Queue stores asynchronous callbacks waiting for execution. The Event Loop continuously checks if the Call Stack is empty, then pushes tasks from the Callback Queue to the Call Stack.
Example:
console.log("Start"); setTimeout(() => console.log("Timeout Callback"), 1000); console.log("End");
Execution Order:
console.log("Start")
executes.setTimeout
moves its callback to the Web API.console.log("End")
executes.- After 1 second, the callback moves to the Callback Queue.
- The Event Loop pushes the callback to the Call Stack when it is empty.
console.log("Timeout Callback")
executes.
5. Microtasks & Macrotasks
Microtasks
Microtasks are executed before macrotasks and include:
- Promises (
.then
,.catch
,.finally
) MutationObserver
queueMicrotask
Macrotasks
Macrotasks include:
setTimeout
setInterval
setImmediate
requestAnimationFrame
Example:
console.log("Start"); setTimeout(() => console.log("setTimeout"), 0); Promise.resolve().then(() => console.log("Promise")); console.log("End");
Execution Order:
console.log("Start")
executes.setTimeout
moves to the Web API (macrotask).Promise.resolve().then()
moves to the Microtask Queue.console.log("End")
executes.- Microtask (
Promise
) executes before the macrotask (setTimeout
). setTimeout
executes last.
Output:
Start End Promise setTimeout
Conclusion
Understanding the JavaScript Event Loop, Call Stack, Web APIs, Callback Queue, and Microtasks & Macrotasks is essential for writing efficient JavaScript code. Mastering these concepts will help you handle asynchronous operations effectively and avoid performance bottlenecks in your applications.
Leave a Comment