Mastering JavaScript Closures, Event Loop, and Asynchrony

author
By Shubham Shukla

5/22/2026

2

Deep-dive into the advanced mechanics of JavaScript. Master lexical scope, closures, execution contexts, call stack, event loop, and async/await.

image

JavaScript is a versatile, single-threaded language that powers the modern web. Many developers learn to write basic JavaScript functions, event listeners, and API calls, but struggle to explain what happens under the hood.

Understanding advanced JavaScript concepts—such as Closures, the Event Loop, and Asynchronous programming mechanics—is what separates junior developers from senior engineers. These topics are also heavily tested in front-end and full-stack interviews.

In this deep-dive tutorial, we explore these advanced JavaScript mechanics with code examples, visualizations, and practical use-cases.


Table of Contents

  1. Execution Context and Call Stack
  2. Lexical Scope and Closures Explained
  3. The Single-Threaded Nature of JavaScript
  4. The Event Loop: Call Stack, Web APIs, and Queues
  5. Microtask Queue vs. Callback Queue (Macrotask)
  6. Asynchronous JavaScript: Promises & Async/Await
  7. Frequently Asked Questions (FAQs)
  8. Conclusion

1. Execution Context and Call Stack

To understand how JavaScript runs code, you must understand the Execution Context. Everything in JavaScript happens inside an Execution Context, which consists of two phases:

  1. Memory Creation Phase: JavaScript scans the code and allocates memory space for variables and functions. Variables are initialized with undefined, while function declarations are stored in their entirety.
  2. Code Execution Phase: JavaScript executes the code line-by-line, assigning actual values to variables and invoking functions.

The Call Stack is a stack data structure that tracks the current execution context. When a function is called, a new execution context is pushed onto the stack. When the function finishes execution, its context is popped off the stack.


2. Lexical Scope and Closures Explained

A Closure is a function that retains access to its lexical scope (outer variables) even when the function is executed outside its original scope.

The Lexical Scope Rule:

JavaScript uses lexical scoping, meaning a function's scope is determined by where the function is defined in the source code, not where it is executed.

Closure Code Example:

function outerFunction(outerVariable) {
  return function innerFunction(innerVariable) {
    console.log(`Outer: ${outerVariable}`);
    console.log(`Inner: ${innerVariable}`);
  };
}

const newFunction = outerFunction("outside");
newFunction("inside"); 
// Output:
// Outer: outside
// Inner: inside

Even though outerFunction finished execution and its context was popped off the call stack, innerFunction still closed over outerVariable and retained access to it in memory.

Practical Use-Case: Data Encapsulation

Closures are used to create private variables that cannot be accessed or modified directly from outside the function:

function createCounter() {
  let count = 0; // Private variable
  return {
    increment: function() { count++; return count; },
    decrement: function() { count--; return count; }
  };
}

const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
// count is inaccessible directly from outside: counter.count returns undefined

3. The Single-Threaded Nature of JavaScript

JavaScript is a single-threaded language, meaning it has a single call stack and can only execute one task at a time.

If JavaScript can only run one task at a time, how does it handle long-running operations—like fetching data from a database or waiting for a timer—without freezing the browser user interface?

It achieves this by offloading asynchronous operations to the browser environment (Web APIs) or the Node.js runtime.


4. The Event Loop: Call Stack, Web APIs, and Queues

The Event Loop is the mechanism that enables JavaScript to perform non-blocking, asynchronous operations.

The Event Loop Architecture:

  • Call Stack: Executes synchronous JavaScript code.
  • Web APIs: Provided by the browser (e.g., setTimeout, fetch, DOM events). When JavaScript calls a Web API, the browser handles the operation in the background.
  • Callback/Callback Queue: When an asynchronous Web API completes, its callback function is pushed to this queue.
  • Event Loop: Monitors the Call Stack and Callback Queue. If the Call Stack is empty, the Event Loop takes the first task from the queue and pushes it onto the Call Stack to execute.

5. Microtask Queue vs. Callback Queue (Macrotask)

JavaScript has two types of asynchronous queues, and they have different execution priorities:

  [Call Stack Empty] 
         |
         v
  [Microtask Queue] (Higher Priority: Promises, MutationObservers)
         |
         v
  [Callback Queue / Macrotask] (Lower Priority: setTimeout, setInterval, I/O)

The Priority Rule:

The Event Loop will execute all tasks in the Microtask Queue before it checks the Callback Queue (Macrotask Queue).

Code Challenge:

console.log("Start");

setTimeout(() => {
  console.log("Timeout (Macrotask)");
}, 0);

Promise.resolve().then(() => {
  console.log("Promise (Microtask)");
});

console.log("End");

Output Order:

  1. Start (Synchronous)
  2. End (Synchronous)
  3. Promise (Microtask) (Microtask Queue runs first)
  4. Timeout (Macrotask) (Callback Queue runs last)

6. Asynchronous JavaScript: Promises & Async/Await

Asynchronous JavaScript has evolved to make code easier to write and read:

  • Callbacks: Passing functions as arguments. Led to nested code structures known as "Callback Hell".
  • Promises: Objects representing the eventual completion (or failure) of an asynchronous operation. They allow chaining using .then() and .catch().
  • Async/Await: Syntactic sugar built on top of Promises, allowing you to write asynchronous code that looks and behaves like synchronous code.
async function fetchUserData() {
  try {
    const response = await fetch("https://api.github.com/users/shbhmexe");
    const data = await response.json();
    console.log(data.name);
  } catch (error) {
    console.error("Failed to fetch data:", error);
  }
}

NOTE

Detailed tutorials on writing asynchronous backend APIs can be found in our Notes Directory.


7. Frequently Asked Questions (FAQs)

Q1. What is the difference between let, const, and var regarding scope?

  • var is function-scoped and undergoes hoisting (initialized with undefined).
  • let and const are block-scoped (confined to {}) and live in the Temporal Dead Zone until initialized, preventing access before definition.

Q2. Does JavaScript run multi-threaded operations in Node.js?

Node.js runs your JavaScript code on a single thread. However, under the hood, Node's C++ bindings utilize the Libuv library, which manages a pool of background worker threads to handle heavy I/O operations (like file system queries and cryptography) asynchronously.

Q3. How do closures cause memory leaks in JavaScript?

Because closures retain references to outer scope variables, those variables cannot be garbage-collected as long as the inner function is active. If you create many closures that reference large objects without releasing them, it can lead to memory leaks.


8. Conclusion

Mastering execution contexts, closures, and the event loop provides a solid foundation for understanding how JavaScript works under the hood. It allows you to write clean, non-blocking, and bug-free web applications, and prepares you for technical interviews. Practice with code examples, analyze runtime behaviors, and keep exploring!

Suggested Images:

  • Featured Image: A structural infographic diagram showing the interactions between the Call Stack, Web APIs, Event Loop, and Task Queues (Prompt: Event loop execution cycle diagram, Call stack, Web APIs, and Microtasks schema, high contrast web developer style).
  • Inline Image: A diagram illustrating how lexical scope scoping looks inside nested functions.

Alt Texts:

  • Featured Image: "JavaScript Event Loop and Call Stack runtime diagram"
  • Inline Image: "Lexical scoping scope chain illustration"

Internal Linking Suggestions:

Popular Tags :

Share this post :

Comments (0)

Leave a Comment

Loading comments...