<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ closures in javascript - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ closures in javascript - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 28 Jul 2026 09:15:23 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/closures-in-javascript/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How Execution Context Works in JavaScript – A Handbook for Devs ]]>
                </title>
                <description>
                    <![CDATA[ Execution Context is one of the most fundamental yet most misunderstood concepts in JavaScript. It defines how JavaScript code is evaluated and executed, and it plays a central role in determining how variables, functions, and scope behave. Many core... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-execution-context-works-in-javascript-handbook/</link>
                <guid isPermaLink="false">696fd4c6078e49955b0f38de</guid>
                
                    <category>
                        <![CDATA[ Execution Context ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Hoisting ]]>
                    </category>
                
                    <category>
                        <![CDATA[ closures in javascript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Scope in js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sumit Saha ]]>
                </dc:creator>
                <pubDate>Tue, 20 Jan 2026 19:17:26 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768848567590/78e00705-493d-4a68-b046-dfcd40a98099.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Execution Context is one of the most fundamental yet most misunderstood concepts in JavaScript. It defines how JavaScript code is evaluated and executed, and it plays a central role in determining how variables, functions, and scope behave.</p>
<p>Many core JavaScript concepts such as scope, hoisting, and closures are closely tied to execution context. Although these topics are often introduced separately, they are all part of the same underlying mechanism. Without a clear understanding of execution context, these concepts can feel disconnected or confusing.</p>
<p>In this handbook, we’ll take a structured and practical approach to understanding execution context in JavaScript. We’ll explore how execution contexts are created, how they work during code execution, and how they explain common JavaScript behaviors.</p>
<p>By the end of this guide, you’ll have a solid mental model of execution context and a stronger foundation for understanding JavaScript at a deeper level.</p>
<h2 id="heading-heres-what-well-cover">Here’s What We’ll Cover:</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-javascript-actually-runs">How JavaScript Actually Runs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-javascript-engine">The JavaScript Engine</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-nodejs-and-v8">Node.js and V8</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-the-javascript-engine-compiles-code">How the JavaScript Engine Compiles Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-interpretation-vs-compilation">Interpretation vs Compilation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-interpretation-works">How Interpretation Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-compilation-works">How Compilation Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-just-in-time-jit-compilation">Just-In-Time (JIT) Compilation</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-introduction-to-javascript-execution-context">Introduction to JavaScript Execution Context</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-an-execution-context">What is an Execution Context?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-global-execution-context">The Global Execution Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-two-phases-of-execution-context">Two Phases of Execution Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-loading-and-execution-phases">Understanding the Loading and Execution Phases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-execution-phase">The Execution Phase</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-hoisting-explained-through-execution-context">Hoisting Explained Through Execution Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary-of-global-execution-context">Summary of Global Execution Context</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-function-execution-context">Function Execution Context</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-comparing-global-and-function-execution-context">Comparing Global and Function Execution Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-function-execution-context-works">How Function Execution Context Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-execution-stack-call-stack">Understanding the Execution Stack (Call Stack)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-the-call-stack-works">How the Call Stack Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-deep-dive-multiple-functions-and-nested-execution">Deep Dive - Multiple Functions and Nested Execution</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-a-practical-example-with-code">A Practical Example with Code</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-creating-the-first-function-execution-context">Creating the First Function Execution Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-scope-chain">Understanding the Scope Chain</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-creating-nested-function-execution-contexts">Creating Nested Function Execution Contexts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-creating-a-deeply-nested-function-execution-context">Creating a Deeply Nested Function Execution Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-var-let-and-const">Understanding var, let, and const</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-the-difference-between-var-and-letconst">Why the Difference Between var and let/const?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-continuing-with-code-execution">Continuing with Code Execution</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-function-returns-and-exits-the-stack">The Function Returns and Exits the Stack</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-scope-through-execution-context">Understanding Scope Through Execution Context</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-scope-works">How Scope Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-problem-with-accessing-inner-scope-variables">The Problem with Accessing Inner Scope Variables</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-connecting-to-scope-understanding">Connecting to Scope Understanding</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-closures-through-execution-context">Understanding Closures Through Execution Context</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-by-step-breakdown-of-a-closure">Step-by-Step Breakdown of a Closure</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-does-a-closure-form">Why Does a Closure Form?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-the-closure">Using the Closure</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary-of-closures">Summary of Closures</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-bringing-it-all-together">Bringing It All Together</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-what-youve-learned">What You've Learned</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-final-words">Final Words</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along and get the most out of this guide, you should have:</p>
<ul>
<li><p>Basic JavaScript (ES6-style) knowledge</p>
</li>
<li><p>Browser and Node.js Environment</p>
</li>
</ul>
<p>I’ve also created a video to go along with this handbook. If you’re the type who likes to learn from video as well as text, you can check it out here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Efqj3FV2vjE" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p><strong>Note:</strong> While prior knowledge of Scope, Hoisting, and Closures is helpful, it's not required. This guide will teach you these concepts through the lens of Execution Context and may even clarify misconceptions you might have about them.</p>
<h2 id="heading-how-javascript-actually-runs">How JavaScript Actually Runs</h2>
<p>Before diving into Execution Context, let's take a step back and understand how JavaScript actually runs – whether in a browser or in a terminal environment. You might wonder why I'm mentioning the terminal. Well, JavaScript now also runs outside the browser through Node.js. So let's first explore how that happens behind the scenes. When it reaches the browser (or in the case of Node.js, the server), the code you write in JavaScript is ultimately executed by the computer. Here's the important part - <strong>computers don't understand JavaScript</strong>. They only understand binary or machine language. So somehow, the browser has to translate your JavaScript code into machine language so that the computer can actually run it.</p>
<p>That means there must be some kind of mechanism inside the browser – or in the Node.js runtime – that performs this translation from your programming language to machine language.</p>
<h2 id="heading-the-javascript-engine">The JavaScript Engine</h2>
<p>That mechanism inside the browser is called the <strong>JavaScript Engine</strong>. In Google Chrome, this engine is known as the V8 Engine. Other browsers use their own engines – Firefox uses SpiderMonkey, Internet Explorer uses Chakra, and Safari uses JavaScriptCore.</p>
<p>No matter which engine it is, every browser has one, and they all perform the same core task: converting your JavaScript code into machine language. Different browsers may implement this process in their own way, but all of them follow the same standard, known as the <strong>ECMAScript specification</strong>.</p>
<p>ECMAScript is basically the official standard that defines how JavaScript should work – like ES5, ES6, and so on. Since each browser's engine implements the standard slightly differently, sometimes the same piece of code may produce slightly different outputs in different browsers.</p>
<p>Anyway, once your code reaches the browser, it's handed over to the browser's JavaScript engine. The engine then converts that code into machine language, which the computer can finally understand. And that's how you get to see the output displayed on your screen.</p>
<p>That's the overall top-level view of how JavaScript code runs. Now, as a programmer, you don't really need to understand what happens at the hardware level, because your focus isn't building hardware – you're an application developer. What truly matters for you, as a JavaScript developer, is understanding what happens <strong>inside</strong> the engine when it runs your code. In other words, you need a clear picture of how the JavaScript engine actually compiles and executes your code. That's the foundation of everything.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914060020/121e3b75-7ddb-462a-b146-547375415d4e.gif" alt="JavaScript Engine" width="1138" height="640" loading="lazy"></p>
<h3 id="heading-nodejs-and-v8">Node.js and V8</h3>
<p>Before we dive deeper, there's one important thing to mention. I've been talking mostly about browsers, so you might be wondering what happens in the case of Node.js? Well, <strong>Node.js actually uses the same V8 engine that powers Google Chrome</strong>.</p>
<p>Ryan Dahl, the creator of Node.js, is a brilliant programmer. What he did was take Chrome's V8 engine – which was already built, tested, and extremely fast – and used it outside the browser. V8 is one of the most powerful and highly optimized compilers in existence. It converts JavaScript into machine language with incredible speed and efficiency.</p>
<p>That's why Google Chrome performs so well – because of the V8 engine. Ryan Dahl realized that V8 was already the best engine out there. So he thought, if he could extract it and use it outside the browser, he wouldn't need to build a new engine from scratch. The compilation part would already be handled by V8. Since V8 is written in C++, Ryan integrated it directly into his own C++ program. In other words, his C++ code and the V8 engine were combined, and that's how the Node.js runtime was created.</p>
<h3 id="heading-how-the-javascript-engine-compiles-code">How the JavaScript Engine Compiles Code</h3>
<p>Now, let's take a look at what actually happens inside a JavaScript engine when it compiles JavaScript code.</p>
<p>To understand that, we need to start with a bit of history. When JavaScript was first introduced, it was an <strong>interpreted language</strong>, meaning there was no compilation process. There wasn't a compiler to convert JavaScript into efficient machine-level code. And here, we come across two important terms -</p>
<ol>
<li><p>Interpretation</p>
</li>
<li><p>Compilation</p>
</li>
</ol>
<p>At first, interpretation and compilation might sound like the same thing – because both convert your code into machine code, right? That's true in essence, but the way they work is completely different.</p>
<h3 id="heading-interpretation-vs-compilation">Interpretation vs Compilation</h3>
<p>Here's what you need to understand. Let’s say you have some JavaScript code that you wrote. This code is readable by humans, but the computer doesn't understand it. Computers only understand binary (zeros and ones). That's machine language, and while the computer understands it perfectly, humans can't read it. So, your job is to take this human-readable JavaScript code and convert it into machine code, so the computer can understand what you're asking it to do.</p>
<p>There are three main ways to perform this conversion:</p>
<ol>
<li><p><strong>Interpretation</strong></p>
</li>
<li><p><strong>Compilation</strong></p>
</li>
<li><p><strong>A hybrid approach</strong> (a mixture of both).</p>
</li>
</ol>
<p>Back in the 90s, JavaScript used to be a purely interpreted language. But in recent times, modern JavaScript engines use a combination of both interpretation and compilation to translate code into machine language. The language itself hasn't changed – it's still JavaScript. But the way it's implemented has evolved dramatically.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914077062/3e95f71d-f54f-480f-bf88-d764efc4f103.gif" alt="Interpretation vs Compilation" width="1138" height="640" loading="lazy"></p>
<h3 id="heading-how-interpretation-works">How Interpretation Works</h3>
<p>Let’s see how an interpreter actually works, meaning how JavaScript code gets converted into machine code through interpretation.</p>
<p>Inside the interpreter, there is already a predefined set of machine-level instructions for every command or expression you can write in JavaScript. To understand this, imagine a piece of JavaScript code that contains several lines of instructions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914092309/68d38c90-92fc-4215-a0c9-9a9e9d0b1868.gif" alt="Interpretation Process" width="1138" height="640" loading="lazy"></p>
<p>The interpreter already knows the machine-level operations that correspond to each of these lines. For example, when two numbers are added, that is an arithmetic operation. When a <code>console.log</code> statement is used, that is an instruction to print something on the screen.</p>
<p>A real program can contain many such instructions. For every one of these operations, the interpreter has a predefined binary or machine-code equivalent. This tells the computer exactly how to execute that specific instruction. When you run a program, the interpreter starts from the very first line and executes the code line by line.</p>
<p>It looks at the first line, recognizes the operation being performed, translates that instruction into machine code, and executes it immediately. Once that line finishes executing, the interpreter moves to the next line. If the next line is a <code>console.log</code> statement, the interpreter translates and executes that instruction as well. This process continues line by line until the program finishes.</p>
<p>But there’s a drawback to this approach: this process is relatively slow. Because the interpreter translates and executes one line at a time, it has to repeatedly switch between reading the source code and executing it. This constant back-and-forth makes pure interpretation significantly slower. This is one of the reasons JavaScript was noticeably slow back in the 90s.</p>
<p>At the same time, interpretation has a major advantage. Since the interpreter executes code one instruction at a time, it can stop immediately if it encounters an error and report exactly where that error occurred. This makes debugging much easier, because developers can quickly identify the problematic line, fix it, and run the code again. So the trade-off is simple: interpretation makes JavaScript easy to debug, but it comes at the cost of slower execution.</p>
<h3 id="heading-how-compilation-works">How Compilation Works</h3>
<p>To overcome that slowness, the concept of compilation was introduced. A compiler works differently: instead of executing code line by line, it takes the entire program at once, translates the whole thing into machine code, and then runs it line by line from that compiled version. This makes the process much faster compared to interpretation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914111246/2f8cffff-d82b-49a1-b36c-3c6f18bf6742.gif" alt="Compilation Process" width="1138" height="640" loading="lazy"></p>
<p>In this process, the program is first converted into machine code in one go. Only after that conversion is complete does execution begin. So rather than constantly translating and executing at the same time, the compiler finishes the translation first, and then the computer runs the already compiled output.</p>
<p>But there is a problem here too. Suppose there is an error in one of the lines of code. The compiler will not stop at that point. It will continue compiling the rest of the program. That means if your program contains faulty logic, such as an infinite loop or something that causes a memory leak, it can still end up being executed and may crash your system. You don’t get the same kind of immediate stop and feedback that you get with interpretation.</p>
<p>So that is one of the major drawbacks of compiled languages. They are harder to debug, and in some cases, they can crash the system. The reason is that the entire code gets compiled first, so you don’t immediately know which exact line caused the problem while the program is being prepared.</p>
<p>To find the issue, you usually have to run the program first, and only then you can detect where the problem actually happens. In short, interpretation makes debugging easier but execution slower. Compilation makes execution faster, but debugging harder and failures more risky.</p>
<h3 id="heading-just-in-time-jit-compilation">Just-In-Time (JIT) Compilation</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914130992/9a326cdc-2933-45ae-9c1b-3f6c7ba0fdf0.gif" alt="JIT Compilation Process" width="1138" height="640" loading="lazy"></p>
<p>Now imagine if there were a way to combine both approaches, meaning fast execution like compilation and easy debugging like interpretation. That is exactly what modern JavaScript engines do using a technique called <strong>Just-In-Time compilation</strong>, or <strong>JIT compilation</strong>.</p>
<p>This idea was popularized in 2008 when Google introduced the V8 engine for Chrome. Instead of choosing between interpretation or compilation, V8 combined both into a single system. The result was a much more balanced execution model.</p>
<p>With JIT compilation, JavaScript code isn’t compiled all at once before execution. At the same time, it’s not interpreted line by line for the entire program either. Instead, the engine starts by interpreting the code so it can run immediately and remain easy to debug.</p>
<p>As the program runs, the engine watches which parts of the code are actually being used. When a particular function or instruction is executed, the JIT compiler steps in and compiles only that specific piece of code into machine code. That compiled version is then executed directly by the computer, which makes it much faster.</p>
<p>For example, when a function like <code>instructionOne</code> runs, the JIT compiler converts just that function into machine code and executes it. If another function is called later and contains an error, the engine can still detect that error immediately and stop execution at that exact point. This keeps the debugging experience similar to interpretation.</p>
<p>This approach allows JavaScript to run much faster than pure interpretation while still providing clear error messages and precise debugging. It may not be as fast as a fully compiled language in every scenario, but in real-world usage, the performance difference is usually unnoticeable.</p>
<p>In simple terms, JIT compilation gives JavaScript the best of both worlds. It’s fast enough to feel compiled, while still being flexible and easy to debug like an interpreted language. This is how modern JavaScript engines, including Node.js, execute code today.</p>
<p>With that understanding in place, we can now move on to the main topic: <strong>JavaScript Execution Context</strong>.</p>
<h2 id="heading-introduction-to-javascript-execution-context">Introduction to JavaScript Execution Context</h2>
<p>Many people start learning directly from the Execution Context, but I believe it's important to first understand how the compilation process works. Now that you have that foundation, when you dive into Execution Context, your brain will be able to connect both parts and visualize the complete picture of how JavaScript truly operates.</p>
<p>I think that <strong>Execution Context is the most important concept in JavaScript</strong>. The reason is simple: if you truly understand how it works, then advanced topics like Hoisting, Scope, Scope Chain, and Closures will become much easier to grasp.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914145507/1c76a15c-f307-4f0a-a6a2-9b6ad516bc5f.gif" alt="Execution Context" width="1138" height="640" loading="lazy"></p>
<p>Let’s start by thinking about how you usually write code. One common strategy is to break your code into smaller parts. These separate pieces of code can have different names – like functions, modules, or packages. But no matter what you call them, their purpose is the same: to break a complex program into smaller, more manageable chunks. This division reduces complexity and makes your code easier to read, maintain, and debug.</p>
<p>Before we dive into execution context itself, let’s look at a small, practical example that we’ll use throughout this section.</p>
<p>In this example, we’ll simulate a simple real-world flow: taking an order, processing it, and completing it. First, we’ll see everything written inside a single function. Then, we’ll refactor the same logic into multiple smaller functions.</p>
<p>The goal here is not performance, but structure. As you read the code below, pay attention to how breaking logic into smaller functions makes the program easier to understand – and how this directly relates to how JavaScript creates execution contexts internally.</p>
<h3 id="heading-code-breakdown">Code Breakdown</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914157870/e78cfb8c-8441-4833-bf76-62f3b6c4292e.gif" alt="Code Breakdown" width="1138" height="640" loading="lazy"></p>
<p>In the animation above, the first example shows all the logic written inside a single function. The second example shows the same logic broken down into multiple smaller functions, where each function handles one specific task. At first glance, the single-function version may seem simpler because everything is written in one place. But in real applications, this approach quickly becomes hard to read, test, and maintain.</p>
<p>Here is the first version of the code, where all the logic lives inside a single function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">takeOrder</span>(<span class="hljs-params"></span>) </span>{
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Taking Order"</span>);
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Processing Order"</span>);
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Completed Order"</span>);
}

takeOrder();
</code></pre>
<p>In a real-world application, things aren’t that simple. Instead of just console logs, there would be complex logic, multiple algorithms, API calls, and data processing happening behind the scenes. That’s why we usually break code into smaller parts, where each part handles one specific responsibility.</p>
<p>Now, here is the same logic rewritten using multiple smaller functions, each responsible for a single step:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">takeOrder</span>(<span class="hljs-params">callback</span>) </span>{
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Taking Order"</span>);
 callback();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processOrder</span>(<span class="hljs-params">callback</span>) </span>{
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Processing Order"</span>);
 callback();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">completeOrder</span>(<span class="hljs-params"></span>) </span>{
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Completed Order"</span>);
}

takeOrder(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
 processOrder(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
 completeOrder();
 });
});
</code></pre>
<p>Now, imagine if you wrote all those complex operations (like taking orders, processing them, and completing them) all inside a single file or function. That would make your code neither easy to read nor easy to maintain. It would quickly become messy and difficult to debug.</p>
<p>But if you break each task into smaller functions, it becomes much easier to maintain, and the overall complexity of the code decreases significantly.</p>
<p>In the same way, <strong>JavaScript also breaks down your code into smaller parts before interpreting it</strong>. This helps reduce the complexity of execution. Each of these smaller units is what we call an <strong>Execution Context</strong>.</p>
<h3 id="heading-what-is-an-execution-context">What is an Execution Context?</h3>
<p>An Execution Context is basically a small, isolated environment where a specific piece of code is interpreted and converted into machine language. So, to make its job easier, the JavaScript engine divides your code into smaller parts and executes them one by one. Each of those parts is an Execution Context.</p>
<p>In this section, you'll learn how Execution Contexts are actually created inside the JavaScript engine – line by line – so you can clearly visualize what happens behind the scenes when your code runs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914176016/88797231-c6d9-4bb5-86bc-c2b78c7c1819.gif" alt="Execution Context Creation" width="1138" height="640" loading="lazy"></p>
<p>In the animation above, one panel shows the code being written, and the other panel shows the execution context being created step by step. Now, at this point, the panel that shows the code is completely empty.</p>
<h3 id="heading-the-global-execution-context">The Global Execution Context</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914194848/35fe6af7-234b-4bfb-83cd-3f6bb3286bca.gif" alt="Global Execution Context" width="1138" height="640" loading="lazy"></p>
<p>Even when there's no code written yet, JavaScript still creates something called a <strong>Global Execution Context</strong> right at the very beginning. Think of the Global Execution Context as a simple object – or you can visualize it as a box, a container that holds everything your program needs to start running.</p>
<p>At the very start, before any code is executed, this Global Execution Context is created. Inside it, you have:</p>
<ul>
<li><p>the <code>window</code> object, which you may already be familiar with,</p>
</li>
<li><p>the <code>this</code> keyword, which initially points to the <code>window</code> object</p>
</li>
<li><p>the Variable Object, and</p>
</li>
<li><p>the Scope Chain.</p>
</li>
</ul>
<h4 id="heading-two-phases-of-execution-context">Two Phases of Execution Context</h4>
<p>There's one more important thing to understand: the Global Execution Context actually goes through <strong>two distinct phases</strong>.</p>
<p>First, we have the <strong>Loading Phase</strong> (also called the <strong>Creation Phase</strong>). During this phase, your code doesn't execute yet. Next, we have the <strong>Execution Phase</strong>. During this phase, your code actually runs.</p>
<p>To summarize, when the Global Execution Context is first created, it contains four main components: <code>window</code>, <code>this</code>, variable object, and scope chain. And before any line of code runs, JavaScript first goes through the Loading Phase.</p>
<h3 id="heading-understanding-the-loading-and-execution-phases">Understanding the Loading and Execution Phases</h3>
<p>Now, let's assume you've written some code. It's just a short seven-line script where you have a variable named <code>topic</code> and a function called <code>getTopic</code> that simply returns that topic:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> topic = <span class="hljs-string">"JavaScript Execution Context"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getTopic</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> topic;
}

<span class="hljs-built_in">console</span>.log(getTopic());
</code></pre>
<p>As you can see in the code below, when the Global Execution Context is created, it already includes <code>window</code>, <code>this</code>, variable object, and scope chain. Along with that, during the Loading Phase, any functions and variables declared in your code – like <code>topic</code> and <code>getTopic</code> – also get added to the Global Execution Context.</p>
<p>But here's an important point: during the Loading Phase, <strong>these variables and functions are only recognized, not yet fully executed</strong>. That means their values are temporarily set to <code>undefined</code> until the actual execution begins.</p>
<p>As I mentioned earlier, there's something inside the Global Execution Context called the Variable Object. During the Loading Phase, JavaScript allocates a specific space in memory for every variable declared in the code.</p>
<p>So, for example, a memory slot is created for your variable <code>topic</code>, and JavaScript assigns it the value <code>undefined</code> at this stage. Similarly, the <code>getTopic</code> function is also stored inside that same Variable Object. But instead of assigning it an undefined value, JavaScript stores a <strong>reference</strong> to the function – meaning the function's entire structure or body is saved somewhere in memory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914211999/e1d29487-6a93-41c3-ae2a-f9de4f14615d.gif" alt="Loading Phase" width="1138" height="640" loading="lazy"></p>
<p>So now, through the Global Execution Context, JavaScript already knows that there's a function called <code>getTopic</code> defined in the program. It hasn't executed it yet, but it's aware that such a function exists and might need to be called later during execution.</p>
<h3 id="heading-the-execution-phase">The Execution Phase</h3>
<p>Once the Creation Phase is complete, JavaScript moves on to the second phase: the Execution Phase. In this phase, the program starts running from the very beginning, line by line.</p>
<p>So when execution begins, it looks at the first line, <code>var topic = "javascript execution context"</code>. Now, JavaScript already knows the variable named <code>topic</code>, because during the Loading Phase, it had already stored it in memory with the value <code>undefined</code>. When the Execution Phase starts, JavaScript simply replaces that <code>undefined</code> with the actual value you've assigned. This is the first time the code truly gets executed.</p>
<p>During the Creation Phase, JavaScript also stored the <code>getTopic</code> function in its memory. It knows that somewhere in this program, there's a function called <code>getTopic</code>. So when it reaches line 7, where the function is called, it retrieves that function reference from memory and executes it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914228537/d3e26830-f545-4ccb-8a9a-4ddbbb6a755e.gif" alt="Execution Phase" width="1138" height="640" loading="lazy"></p>
<h3 id="heading-hoisting-explained-through-execution-context">Hoisting Explained Through Execution Context</h3>
<p>Now imagine you write <code>console.log(topic)</code> at the very top of your code – meaning you're trying to use the variable before it's even declared.</p>
<p>In <a target="_blank" href="https://www.youtube.com/watch?v=NSSYZJruvyo&amp;feature=youtu.be">earlier tutorials on JavaScript Hoisting</a>, I explained this concept, but not in this much detail – and not in the context of the Execution Context.</p>
<p>Back then, I said that during hoisting, JavaScript conceptually moves all variable declarations to the top of the scope, though only the declarations – not the actual values. But now, through the lens of the Execution Context, you'll understand what really happens behind the scenes.</p>
<p>Here’s the same example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(topic);

<span class="hljs-keyword">var</span> topic = <span class="hljs-string">"JavaScript Execution Context"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getTopic</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> topic;
}

getTopic();
</code></pre>
<p>As you saw above, during the Loading (Creation) Phase, JavaScript already stored the variable <code>topic</code> in memory and assigned it the default value <code>undefined</code>. It also stored the <code>getTopic</code> function in memory as a complete function. That’s why, when execution starts and JavaScript reaches the very first line, it can <em>already</em> find <code>topic</code> in memory, even though the assignment hasn’t happened yet.</p>
<p>Since the value is still the default one from the Loading Phase, the <code>console</code> prints <code>undefined</code>. Then the program continues line by line. When JavaScript reaches this line <code>var topic = "JavaScript Execution Context"</code>, this is the moment the <code>value</code> actually gets assigned. In other words, the engine updates the value of <code>topic</code> inside the current execution context from <code>undefined</code> to "JavaScript Execution Context".</p>
<p>After this point, any code that reads <code>topic</code> will see the updated <code>value</code>. For example, if you place a <code>console.log(topic)</code> below the assignment, it will print the correct <code>string</code>, because the value is no longer <code>undefined</code>.</p>
<p>The same idea applies when <code>getTopic()</code> is called. JavaScript already has the <code>function</code> stored in memory, so it can execute it immediately when the call happens. Inside that function, it looks up <code>topic</code> and returns the value that is currently stored in memory. If the assignment has already run, <code>getTopic()</code> returns "JavaScript Execution Context".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914248559/71dfa2d7-b862-4560-916d-9a9788fc6ab9.gif" alt="Hoisting Explained" width="1138" height="640" loading="lazy"></p>
<p>So if you’ve watched my <a target="_blank" href="https://www.youtube.com/watch?v=NSSYZJruvyo&amp;feature=youtu.be">earlier hoisting tutorial</a> and now you’re reading this guide, you should finally see <em>why</em> this behavior happens inside the JavaScript engine. Explaining hoisting as <strong>“variables being moved to the top”</strong> was a simplified way to help visualize it. The actual reason is that the variable is created in memory during the Loading Phase with a default value, and only later updated during the Execution Phase when the assignment line runs.</p>
<h3 id="heading-summary-of-global-execution-context">Summary of Global Execution Context</h3>
<p>To summarize, the Global Execution Context is basically a JavaScript object. At the very beginning, it contains the <code>window</code> object (if you're in a browser environment), the <code>global</code> object (if it's Node.js), a <code>this</code> object that points to that same <code>window</code> or <code>global</code>, all variables declared in your code stored inside something called the <code>variable object</code>, and any functions you define (that are also stored there, but only as references – meaning JavaScript just keeps a pointer to their full body in memory).</p>
<p>It also keeps something called a <strong>Scope Chain</strong>. As you may know, JavaScript uses lexical scoping – meaning each function knows exactly where it was written and can access variables from its outer scopes. So, JavaScript maintains all these scopes together inside the Scope Chain.</p>
<h2 id="heading-function-execution-context">Function Execution Context</h2>
<p>By this point, you should understood how the Global Execution Context works. The good news is that after this, you only need to understand one more type of Execution Context: the <strong>Function Execution Context</strong>. The interesting thing is, it's almost identical to the Global Execution Context. The only difference is that it's created every time a function is called.</p>
<h3 id="heading-comparing-global-and-function-execution-context">Comparing Global and Function Execution Context</h3>
<p>Let's quickly recall what happened inside the Global Execution Context. It created a global object, created a <code>this</code> object, allocated memory for variables and functions, and initially assigned all variables the value <code>undefined</code>.</p>
<p>Now, if you think carefully, which of these four steps do you think won't be necessary when a function gets executed? Exactly: the Global Object shouldn't get created again inside a Function Execution Context. Because the entire program already has one Global Object that was created earlier, and all functions can access it when needed.</p>
<p>So, instead of creating a new Global Object, something new happens inside the Function Execution Context: it creates an <strong>"arguments object"</strong>. This object holds all the parameters passed to that function. That means whenever you define a function in JavaScript and it has parameters, JavaScript automatically creates an object called <code>arguments</code> inside that function's Execution Context to store those values. If you write <code>console.log(arguments)</code> inside the function body, you'll see all the passed parameters neatly stored as key-value pairs within that <code>arguments</code> object.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914263687/9c024735-6112-475d-9915-4f503ad466cb.gif" alt="Function Execution Context" width="1138" height="640" loading="lazy"></p>
<p>So the only structural difference between the Function Execution Context and the Global Execution Context is this: Global Execution Context contains a <strong>Global Object</strong>, and Function Execution Context contains an <strong>Arguments Object</strong>. Everything else remains exactly the same.</p>
<p>Simply put, think of the Global Execution Context as an entire world. Whenever you call a function, a new world is created inside that global world, following the same structure and behavior.</p>
<h3 id="heading-how-function-execution-context-works">How Function Execution Context Works</h3>
<p>When a function is called, JavaScript creates a completely separate Execution Context for it. Inside that context, it builds an <code>arguments</code> object to hold all the parameters, creates a <code>this</code> object as usual, and allocates memory for all the variables and inner functions defined inside that function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914281788/81ca6cfe-1bb5-44f6-9647-9daaa1c5fc83.gif" alt="Function Execution Context Creation" width="1138" height="640" loading="lazy"></p>
<p>That means <strong>hoisting also applies inside functions</strong>. During the Creation Phase, JavaScript will assign <code>undefined</code> to all variables within that function, and that's exactly why hoisting happens there, too.</p>
<h3 id="heading-understanding-the-execution-stack-call-stack">Understanding the Execution Stack (Call Stack)</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914298723/60a5c807-a77a-481e-8ce8-157468f946cd.gif" alt="Execution Stack" width="1138" height="640" loading="lazy"></p>
<p>Now, remember how I mentioned earlier that in JavaScript, one function can contain another function? This naturally means that multiple Execution Contexts can exist at the same time.</p>
<p>Here’s a simple example to visualize that idea:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">one</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">two</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">three</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-comment">// some logic here</span>
    }
    three();
  }
  two();
}

one();
</code></pre>
<p>In this example, functions are called one after another, but not all at once. Each time a function is called, JavaScript creates a new Function Execution Context for it.</p>
<p>This is where the <strong>Call Stack</strong> comes in.</p>
<p>The Global Execution Context is created first and stays at the bottom. When <code>one()</code> is called, its execution context is created and placed on top of the stack. Inside <code>one()</code>, when <code>two()</code> is called, a new execution context for <code>two()</code> is added on top of <code>one()</code>. Then, when <code>three()</code> is called, its execution context is added on top of <code>two()</code>.</p>
<p>At this point, the call stack looks something like this (from bottom to top):</p>
<ul>
<li><p>Global Execution Context</p>
</li>
<li><p><code>one()</code> Execution Context</p>
</li>
<li><p><code>two()</code> Execution Context</p>
</li>
<li><p><code>three()</code> Execution Context</p>
</li>
</ul>
<p>Once <code>three()</code> finishes executing, its execution context is removed from the stack. Control returns to <code>two()</code>. When <code>two()</code> finishes, its execution context is removed, and control returns to <code>one()</code>. Finally, when <code>one()</code> finishes, its execution context is also removed, leaving only the Global Execution Context.</p>
<p>Because JavaScript is a single-threaded language, all of this happens on one main thread. That same thread is responsible for creating execution contexts, placing them on the call stack, and removing them once their work is done. This stacking and unstacking of execution contexts is exactly what we refer to as the <strong>Execution Stack</strong>, or more commonly, the <strong>Call Stack</strong>.</p>
<h3 id="heading-how-the-call-stack-works">How the Call Stack Works</h3>
<p>JavaScript actually stores these contexts one on top of another, just like a stack. And this stacking structure is called the Call Stack.</p>
<p>At the very beginning, JavaScript places the Global Execution Context at the bottom of the stack. Then, whenever a function is called, a new Function Execution Context is created and pushed on top of it. If that function calls another function inside it, another context is stacked above that, and so on.</p>
<p>In this way, JavaScript keeps adding and removing Execution Contexts in a stacked order as the program runs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914317836/1aadf895-8dd8-4849-8128-4093f03a5128.gif" alt="How the Call Stack Works" width="1138" height="640" loading="lazy"></p>
<p>So now you have a complete picture of what an Execution Context really is, and its types:</p>
<ol>
<li><p>The Global Execution Context</p>
</li>
<li><p>The Function Execution Context</p>
</li>
</ol>
<h3 id="heading-deep-dive-multiple-functions-and-nested-execution">Deep Dive – Multiple Functions and Nested Execution</h3>
<p>So far, we’ve only seen how the Execution Context works in the Global Scope, or when a function is called directly from the Global Scope. But what if you have multiple functions? Or if one function contains another function – in other words, nested functions? How does the Execution Context behave then?</p>
<p>Every time JavaScript creates an Execution Context, it needs to keep track of it somewhere in memory. There has to be some logic to determine which context should run first, and which one should execute next. To manage all of that, JavaScript needs to maintain a specific data structure, right?</p>
<p>And that data structure is called the Execution Stack. It's actually based on a <strong>Stack</strong> data structure. Think of it like stacking books on a table: you place one book on top of another. Similarly, JavaScript stacks each Execution Context on top of the previous one inside the Execution Stack.</p>
<p>Now, a stack has one special property: the last item that goes in is always the first one to come out. In short, it follows the <strong>LIFO</strong> rule, or <strong>Last In, First Out</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914336897/3f7f132e-6f4d-4316-8673-ad3c84371564.gif" alt="Deep Dive - Multiple Functions" width="1138" height="640" loading="lazy"></p>
<h2 id="heading-a-practical-example-with-code">A Practical Example with Code</h2>
<p>Alright, let's connect this idea with your code. You know that whenever you run a JavaScript program, the Global Execution Context is created first. Whether your file contains code or not, this Global Context will always be created automatically. And once it's created, JavaScript places this Global Execution Context at the very bottom of the Execution Stack. That's where everything begins.</p>
<p>Let’s look at an example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914357014/eb12c8a3-65c4-4e63-a0ca-7facc207a7e4.gif" alt="Practical Example" width="1138" height="640" loading="lazy"></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> a = <span class="hljs-number">1</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">one</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(a);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">two</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(b);

    <span class="hljs-keyword">var</span> b = <span class="hljs-number">2</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">three</span>(<span class="hljs-params">d</span>) </span>{
      <span class="hljs-built_in">console</span>.log(c + d);
      <span class="hljs-keyword">let</span> c = <span class="hljs-number">3</span>;
    }

    three(<span class="hljs-number">4</span>);
  }

  two();
}

one();
</code></pre>
<p>In the above code, you have three things: a variable declared with <code>var a</code>, a function called <code>one</code> with its definition, and finally a call or invocation of that function. These three (the variable <code>a</code>, the function <code>one</code>, and its invocation) all exist in the <strong>Global Scope</strong>, or the root level of the program.</p>
<p>Inside the body of the <code>one</code> function, there's another nested function called <code>two</code>, and inside <code>two</code>, there's yet another function called <code>three</code>. These nested functions are not part of the Global Scope – rather, they belong to their respective inner scopes.</p>
<p>So, during the Creation Phase, JavaScript allocates memory for the variable <code>a</code> (initially setting it to <code>undefined</code>) and stores a reference to the function <code>one</code> in the global memory/variable environment so it can be invoked later during execution.</p>
<p>Since there's nothing else in the Global Scope, JavaScript then moves on to the <strong>Execution Phase</strong>. In this phase, execution starts line by line. First, it updates the value of <code>a</code> from <code>undefined</code> to <code>1</code>. Then it moves to the next line, where it finds the function definition of <code>one</code>. Since that function's reference is already stored in the Scope Chain, JavaScript skips over the function body for now and continues to the next line – the point where <code>one()</code> is actually invoked.</p>
<h3 id="heading-creating-the-first-function-execution-context">Creating the First Function Execution Context</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914376840/8e10ea3b-ad5a-4872-b9d6-44c728cf81d3.gif" alt="First Function Execution Context" width="1138" height="640" loading="lazy"></p>
<p>As soon as the <code>one</code> function is invoked, JavaScript creates a brand-new Function Execution Context inside the Execution Stack, placed right above the Global Execution Context. When this new context for <code>one</code> is created, it first enters its Loading Phase. Since the <code>one</code> function doesn't take any arguments, the <code>arguments</code> object inside this Execution Context will remain empty.</p>
<p>Then comes the <code>this</code> reference, which points to the global object – in this case, the <code>window</code> object. After that, you have the Scope Chain and the Variable Object. Inside the Variable Object, there's only the <code>two</code> function. Why? Because inside the body of <code>one</code>, there are no local variables declared – only a <code>console.log</code> statement that tries to print <code>a</code>.</p>
<p>But since the variable <code>a</code> is not defined inside <code>one</code>, it doesn't appear in this context's Variable Object. Instead, JavaScript will later look for it in the outer scope using the Scope Chain. But the <code>one</code> function body does contain another function declaration: the <code>two</code> function. So, during the Loading Phase, JavaScript stores that <code>two</code> function inside the Variable Object, just like it stored the function definitions earlier in the Global Execution Context. It follows the exact same process, only this time, it's happening inside the function's own scope.</p>
<p>Alright, now let's check if there's anything else inside the body of the <code>one</code> function that needs to be added to its Variable Object. The answer is no – there's nothing else.</p>
<p>So next, JavaScript moves to the Execution Phase, and just like in the Global Execution Context, it starts executing line by line. The first line inside the <code>one</code> function is <code>console.log(a)</code>. At this point, JavaScript checks whether the variable <code>a</code> exists inside the Variable Object of the current Execution Context. It looks and finds nothing.</p>
<p>Since the variable <code>a</code> isn't declared inside the <code>one</code> function, JavaScript moves to the next step – it follows the Scope Chain to look into its parent scope. Now, what's inside the parent scope? Yes: the variable <code>a</code> is there, defined in the Global Execution Context. So JavaScript retrieves that value and prints it in the console.</p>
<h3 id="heading-understanding-the-scope-chain">Understanding the Scope Chain</h3>
<p>It's important to clearly understand one thing here: the Scope Chain is essentially a <strong>Lexical Environment</strong>. This means that every scope is connected to its parent scope in a linked structure. The term <em>"chain"</em> is used because each scope holds a reference to its parent or ancestor scopes, forming an actual chain-like connection.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914430035/232299ef-fad9-4b82-b670-d30a6eddc582.png" alt="Scope Chain" width="2560" height="1440" loading="lazy"></p>
<p>That's why, when JavaScript couldn't find the variable <code>a</code> in the <code>one</code> function's own Variable Object, it followed that chain upward (to its parent or ancestor scopes) and successfully found <code>a</code> in the Global Scope.</p>
<h3 id="heading-creating-nested-function-execution-contexts">Creating Nested Function Execution Contexts</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914449920/0619d977-a5a8-4524-b29d-6afa628c8223.gif" alt="Creating Nested Function Execution Contexts" width="910" height="512" loading="lazy"></p>
<p>After printing the value of <code>a</code>, the program moves to the next line. There it finds the body of the <code>two</code> function.</p>
<p>But at this stage, JavaScript doesn't need to do anything with it. This is because during the Loading Phase, the reference to <code>two</code> has already been stored in memory. So it skips over the function body and moves to the next line, where it sees that <code>two()</code> is being invoked.</p>
<p>Since the <code>two</code> function is now being called, JavaScript creates a brand-new Function Execution Context for it, and places it on top of the Execution Stack. Just like before, when this new <code>two</code> Execution Context is created, it first goes through its Loading Phase. During this phase, it populates its Scope Chain, meaning it links itself with the Variable Objects of its parent or ancestor scopes.</p>
<p>Inside the body of <code>two</code>, there's a variable named <code>b</code>, so in this new context's Variable Object, JavaScript stores <code>b</code> with the initial value <code>undefined</code>. Then it finds another function definition, <code>three</code>. So, just like before, JavaScript stores the reference to the <code>three</code> function inside the Variable Object of <code>two</code>.</p>
<p>Then in the next line, the program moves to where the function <code>three</code> is called. Since it's still in the loading phase, there's nothing to execute yet. That part is done, so now it enters the execution phase and starts running each line one by one.</p>
<p>Inside the function <code>three</code>, what's the first line? It's a console log of the variable <code>b</code>. But that variable hasn't been initialized yet. In this context, its value is still <code>undefined</code>. So, when the program runs that line, it prints <code>undefined</code>. Now you can clearly see why during hoisting, variables often print <code>undefined</code>.</p>
<p>Once you understand how the Execution Context works, many other tricky behaviors of JavaScript start to make sense. So pay close attention and try to grasp these terms deeply.</p>
<p>Alright, after that, in the next line, the variable's value is being assigned. So, the value of <code>b</code> changes from <code>undefined</code> to <code>2</code>. Then in the following line, you see the definition of the <code>three</code> function. The Execution Context doesn't need to do anything here, so it simply skips over this line. The next line shows that the <code>three</code> function is being invoked – and not just that, it's being called with an argument, <code>4</code>.</p>
<h3 id="heading-creating-a-deeply-nested-function-execution-context">Creating a Deeply Nested Function Execution Context</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914468117/6ac0a389-df4b-4e85-be85-2abf84106ad7.gif" alt="Creating a Deeply Nested Function Execution Context" width="1138" height="640" loading="lazy"></p>
<p>Since the <code>three</code> function has been invoked, a brand-new Execution Context is created inside the execution stack. During the Loading Phase of the <code>three</code> Execution Context, you can already see that there's a value inside the arguments. At index 0, it's <code>4</code>. That's because when the function was called, the value <code>4</code> was passed in.</p>
<p>And here's something interesting: look at how you named the parameter inside the <code>three</code> function. It's called <code>d</code>, right? So, during the Loading Phase itself, a variable named <code>d</code> appears inside the context, and it's already assigned the value <code>4</code>. Then it moves to the next line. There's a <code>console.log</code> statement, but nothing special happens there yet. After that, you have <code>let c = 3;</code> – and this is where things get a bit different.</p>
<h3 id="heading-understanding-var-let-and-const">Understanding var, let, and const</h3>
<p>You see, although <code>var</code>, <code>let</code>, and <code>const</code> are all used to declare variables, their behaviors are not the same. For <code>var</code>, during the Loading Phase, JavaScript automatically allocates memory and sets its value to <code>undefined</code>. But for <code>let</code> and <code>const</code>, JavaScript still allocates memory during the Loading Phase.</p>
<p>The difference is, they remain inside what's called the <strong>Temporal Dead Zone (TDZ)</strong> until the actual line of code where they are declared is reached. That means, even though they exist inside the Execution Context, they can't be accessed through the Variable Object yet.</p>
<p>So you might be wondering, what is the Temporal Dead Zone? It's the period between a variable being created in memory and being initialized with a value. During this time, the variable technically exists, but since no value has been assigned, JavaScript keeps it temporarily inaccessible. If you try to access that variable during the TDZ, you'll immediately get a ReferenceError.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914488166/993ea67c-5d61-4e22-a9fe-0e8c254206de.png" alt="Temporal Dead Zone" width="2560" height="1440" loading="lazy"></p>
<p>In simple terms, the program knows that the variable exists, but it's not ready to be used yet. And until the code execution reaches that specific declaration line, you won't be able to access it from the Variable Object either. You can think of it like an iPhone's locked screen: the phone is there, but until you enter the PIN and unlock it, you can't do anything with it.</p>
<h3 id="heading-why-the-difference-between-var-and-letconst">Why the Difference Between var and let/const?</h3>
<p>Now, many people wonder, doesn't the same thing happen with <code>var</code>? Why does JavaScript assign <code>undefined</code> to variables declared with <code>var</code>, but keeps <code>let</code> and <code>const</code> inside the TDZ instead of doing the same?</p>
<p>Excellent question! The main reason is that <code>var</code> comes from the older versions of JavaScript – specifically ES5 and earlier – where there was no concept of safety checks or the Temporal Dead Zone. Back then, JavaScript didn't want the program to crash if a variable was accessed before initialization. So, to avoid breaking the program, it would automatically assign <code>undefined</code> as a fallback value.</p>
<p>But <code>let</code> and <code>const</code> were introduced in ES6, where the goal was to make the language safer and more predictable. If JavaScript had assigned <code>undefined</code> to them as well, it would have created the illusion that the variable was properly initialized, even though it wasn't. So, JavaScript intentionally blocks access to those variables during that time to signal to developers, "The variable exists, but it's not ready to be used yet." This is a key difference that makes your code safer and helps catch bugs earlier in the development process.</p>
<h3 id="heading-continuing-with-code-execution">Continuing with Code Execution</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914508229/8db66c5a-6941-40f6-9ead-ffb08ce36a65.gif" alt="Continuing with Code Execution" width="1138" height="640" loading="lazy"></p>
<p>Now let's get back to the flow. At this point, inside the <code>three</code> function, there's nothing else left to load, so it moves to the Execution Phase.</p>
<p>In the first line, you have a console log printing <code>c + d</code>. You already know that the value of <code>d</code> is <code>4</code>, but the variable <code>c</code> is still inside the Temporal Dead Zone – meaning it can't be accessed yet. So this line will throw a <strong>ReferenceError</strong>, because the program can't reference <code>c</code> from memory at that point. But if you had written the code the other way around (first declaring <code>let c = 3</code>, and then logging it in the next line), the behavior would have been completely different.</p>
<p>In that case, during the creation phase, <code>c</code> would still start in the Dead Zone, but by the time the execution reached that line, its value would already be assigned. Then, when the console log ran, both <code>c</code> and <code>d</code> would be accessible, and their values would print correctly. I hope that’s clear now.</p>
<p>So, you can now see how JavaScript actually works behind the scenes. You've also learned how hoisting truly operates at a machine level through the concept of the Execution Context.</p>
<h3 id="heading-the-function-returns-and-exits-the-stack">The Function Returns and Exits the Stack</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914532636/53263269-f4bf-4ae6-9dab-a85209bcb8e4.gif" alt="Function Returns and Exits the Stack" width="1138" height="640" loading="lazy"></p>
<p>Alright, now let's move forward. Inside the <code>three</code> function, once the <code>console.log</code> runs successfully, it will print <code>7</code>. After that, is there anything else left in the function? No, there isn't. Since there are no more lines to execute, the work of the <code>three</code> function is complete. Whenever a function finishes its job, it immediately gets popped out from the execution stack. That means, since the <code>three</code> function has finished executing, it will be removed from the stack following the LIFO (Last In, First Out) rule.</p>
<p>Now, what’s at the top of the stack? The <code>two</code> function. If you check the body of <code>two</code>, do you see any remaining lines to execute? No, it's done too. So, <code>two</code> will also exit from the execution stack. Finally, since there's nothing left to run in <code>one</code>, that function will also pop out, leaving the execution stack completely empty.</p>
<p>Since there are no more functions left to execute, the Global Execution Context will also exit from the execution stack. But if there had been more code to run in the global scope (for example, another function call right after <code>one()</code>) then the Global Execution Context wouldn't have been removed yet. Instead, it would have continued executing the next function just like before.</p>
<h2 id="heading-understanding-scope-through-execution-context">Understanding Scope Through Execution Context</h2>
<p>Now, let's move on to another important concept: <strong>Scope</strong>. We’ve discussed Scope a bit already, but this time, you'll understand how Scope works in relation to the Execution Context.</p>
<p>Take a look at this simple example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hello</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> message = <span class="hljs-string">"hello world"</span>;
}

hello();
<span class="hljs-built_in">console</span>.log(message);
</code></pre>
<p>Here, you have a function called <code>hello</code>. Inside it, there's a variable named <code>message</code> declared with <code>var</code>, which holds a certain value. Outside the function – that is, in the global scope – you're calling or invoking the <code>hello</code> function, and in the next line, you're trying to print the <code>message</code> variable using <code>console.log</code>. It's a very simple setup.</p>
<h3 id="heading-how-scope-works">How Scope Works</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914550328/f495fae7-6765-4a9b-a6b1-88423c405315.gif" alt="How Scope Works" width="1138" height="640" loading="lazy"></p>
<p>So, based on everything you've learned so far, what will happen if you run this program? First, the Global Execution Context will go through its Creation Phase. During this phase, it will find a function named <code>hello</code>, and store its reference inside the Variable Object.</p>
<p>Once that's done, there's nothing else left for the Creation Phase. Perfect. Now the Execution Phase begins. The first line is the definition of the <code>hello</code> function. Since you're in the Execution Phase, there's nothing to execute here – the function's reference is already stored in memory. So the program moves on to the next statement, where the <code>hello</code> function is invoked.</p>
<p>As soon as that happens, a new Execution Context for the <code>hello</code> function is created. Inside the Creation Phase of the <code>hello</code> function's Execution Context, the variable <code>message</code> is placed inside the Variable Object with the value <code>undefined</code>. Once the creation phase is complete, the program moves to the Execution Phase, where the variable <code>message</code> gets its actual assigned value instead of <code>undefined</code>. So, in the execution phase, the value of the <code>message</code> variable becomes <code>"hello world"</code>.</p>
<p>After that, does the <code>hello</code> function have anything else to do? No, it doesn't. So, the <code>hello</code> function's Execution Context will now be popped off or destroyed. That means the program returns to the Global Execution Context.</p>
<h3 id="heading-the-problem-with-accessing-inner-scope-variables">The Problem with Accessing Inner Scope Variables</h3>
<p>Now what happens next? After the <code>hello</code> function is invoked, the next line is <code>console.log(message)</code>. So, the program will now try to print <code>message</code>.</p>
<p>But wait – is the <code>message</code> variable declared inside the Global Execution Context's Variable Object? No, it isn't. That variable was created inside the Function Execution Context, and when that function finished executing, its Execution Context – along with its Scope Chain and Variable Object – was completely removed from memory. That's why, when the console tries to access <code>message</code>, <strong>JavaScript throws a ReferenceError</strong>.</p>
<h3 id="heading-connecting-to-scope-understanding">Connecting to Scope Understanding</h3>
<p>Can you relate this now? If you’ve seen my earlier <a target="_blank" href="https://youtu.be/NtHgwL3uubk">tutorials on Scope</a>, you might remember this concept: a child can always access or inherit things from its parent, but a parent can never access what belongs to the child.</p>
<p>In those tutorials, it was just an example. But now, you can actually visualize how the program manages all of this behind the scenes. That means, while understanding Execution Context, you've rediscovered the concept of Scope in a much clearer, more practical way.</p>
<h2 id="heading-understanding-closures-through-execution-context">Understanding Closures Through Execution Context</h2>
<p>Now, let's move on to another very important topic: <strong>Closures</strong>. Just like you visualized Execution Context earlier, you'll now see how a Closure is created and how it works step by step.</p>
<p>Here's an example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> sum = <span class="hljs-number">0</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">doSum</span>(<span class="hljs-params">a</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">b</span>) </span>{
        <span class="hljs-keyword">return</span> a + b;
    };
}

<span class="hljs-keyword">var</span> temp = doSum(<span class="hljs-number">2</span>);
sum = sum + temp(<span class="hljs-number">8</span>);
</code></pre>
<h3 id="heading-step-by-step-breakdown-of-a-closure">Step-by-Step Breakdown of a Closure</h3>
<p>First, the program creates the Global Execution Context. You're now in the Creation Phase. During this phase, the program scans through the code and finds a variable named <code>sum</code> and a function named <code>doSum</code>. So, memory is allocated for <code>sum</code>, and its initial value is set to <code>undefined</code>. The entire function definition of <code>doSum</code> is stored in memory as a reference.</p>
<p>Once the Creation Phase is complete, the Execution Phase begins. In the Execution Phase, the first line sets <code>sum = 0</code>. Next, the program skips over the <code>doSum</code> function since it's only a definition. Then it moves to the line <code>var temp = doSum(2)</code>. Here, the function is being called, so a brand-new Function Execution Context is created for <code>doSum</code>.</p>
<p>Now, the Creation Phase of that Function Execution Context begins. The parameter <code>a</code> receives the value <code>2</code>, so in memory you have <code>a = 2</code>. Inside the function, there's an anonymous function being returned, and that function's reference also gets stored in memory.</p>
<p>Once the Creation Phase is done, the Execution Phase starts. During this Execution Phase, the <code>doSum</code> function doesn't perform any calculation. Instead, it simply returns that anonymous function. When that happens, the <code>doSum</code> Execution Context is popped off the stack. But something very important also occurs at that exact moment: <strong>a Closure is created</strong>.</p>
<h3 id="heading-why-does-a-closure-form">Why Does a Closure Form?</h3>
<p>Why does that happen?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914623042/c413cec0-2988-48fd-ab58-8ddd0b06741d.gif" alt="Why Does a Closure Form" width="1138" height="640" loading="lazy"></p>
<p>Because when the anonymous function is returned, it still remembers the data from its outer scope – in this case, <code>a = 2</code>. Even though the <code>doSum</code> function itself gets destroyed, its <strong>lexical environment</strong> doesn't disappear completely. JavaScript realizes that this inner function might be called again later, and when that happens, it will need access to those outer variables. So, it preserves that environment in a separate structure called the <strong>Closure Scope</strong>.</p>
<h3 id="heading-using-the-closure">Using the Closure</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766914654725/9c21bce7-5c96-4bdd-8feb-5e861dd499b2.gif" alt="Using the Closure" width="1138" height="640" loading="lazy"></p>
<p>Next, the code moves to the line <code>sum = sum + temp(8)</code>. Here, the function is called again, meaning <code>temp(8)</code> is invoked. This creates a new Execution Context for the anonymous function. During its Creation Phase, the parameter <code>b</code> is assigned the value <code>8</code>. When the Execution Phase begins, the function executes <code>return a + b</code>.</p>
<p>Now, since <code>a</code> doesn't exist in the current scope, JavaScript follows the scope chain and looks into the outer scope – which is the <strong>Closure Scope</strong>. There it finds <code>a = 2</code>, performs the calculation <code>2 + 8 = 10</code>, and returns the result <code>10</code>. At that point, the <code>temp</code> function's Execution Context completes its job and gets popped off from the stack.</p>
<h3 id="heading-summary-of-closures">Summary of Closures</h3>
<p>So, in the line <code>sum = sum + temp(8)</code>, the value of <code>sum</code> was initially <code>0</code>. That means it becomes <code>sum = 0 + 10</code>. Now where did that <code>10</code> come from? It came from the <code>temp</code> function's Execution Context.</p>
<p>Now you can clearly see how a Closure actually works. A Closure is basically a mechanism that keeps a function connected to its outer environment, even after the outer function has been destroyed**.** This is one of JavaScript's most magical yet completely logical behaviors – and it all originates from the concept of the Execution Context itself.</p>
<h2 id="heading-bringing-it-all-together">Bringing It All Together</h2>
<p>So, everything you've seen so far – this is what <strong>JavaScript's Execution Context truly is</strong>. By understanding just this one topic, you've been able to uncover how JavaScript actually works behind the scenes.</p>
<p>You discovered how scopes are formed and how confusing topics like Closures and Hoisting really operate logically within the language. All this time, you may have just been repeating what you heard – "Hoisting means variables are lifted to the top" and "Closure means a function stays connected to its outer environment". But after reading this guide, you should now have a clear, inside-out understanding of how and why JavaScript behaves this way.</p>
<h2 id="heading-summary">Summary</h2>
<p><strong>Execution Context</strong> is one of the most fundamental concepts in JavaScript that explains how the JavaScript engine actually runs your code behind the scenes.</p>
<h3 id="heading-what-youve-learned">What You’ve Learned</h3>
<ol>
<li><p><strong>How JavaScript Engines Work</strong> - The guide started out by explaining that JavaScript engines (like V8 in Chrome and Node.js) convert your human-readable code into machine language that computers can understand. It covered the evolution from simple interpretation to modern Just-In-Time (JIT) compilation, which combines the ease of debugging with fast execution.</p>
</li>
<li><p><strong>What an Execution Context really is</strong> - An Execution Context is a small, isolated environment where JavaScript interprets and executes specific pieces of your code. Think of it as a container that holds everything needed to run a particular section of code.</p>
</li>
<li><p><strong>Two Types of Execution Contexts</strong> -</p>
<ul>
<li><p><strong>Global Execution Context</strong> – Created automatically when your program starts, containing the global object (<code>window</code> in browsers, <code>global</code> in Node.js), the <code>this</code> keyword, a variable object, and the scope chain</p>
</li>
<li><p><strong>Function Execution Context</strong> – Created every time a function is called, similar to the Global Context but with an arguments object instead of a global object</p>
</li>
</ul>
</li>
<li><p><strong>Two Phases of Execution</strong> – Every Execution Context goes through two phases -</p>
<ul>
<li><p><strong>Creation Phase (Loading Phase)</strong> - JavaScript scans your code and allocates memory for variables (setting them to <code>undefined</code>) and stores function references, but doesn't execute anything yet</p>
</li>
<li><p><strong>Execution Phase</strong> - Your code runs line by line, and variables get their actual assigned values</p>
</li>
</ul>
</li>
<li><p><strong>The Call Stack</strong> - JavaScript manages multiple Execution Contexts using a stack data structure called the Call Stack or Execution Stack. It follows the LIFO (Last In, First Out) rule, meaning the last function added is the first one removed when it finishes executing.</p>
</li>
<li><p><strong>Hoisting Explained</strong> - Through Execution Context, you should now truly understand why hoisting happens. Variables declared with <code>var</code> are set to <code>undefined</code> during the Creation Phase, which is why you can reference them before their declaration (they return <code>undefined</code>). Variables declared with <code>let</code> and <code>const</code> remain in the Temporal Dead Zone (TDZ) until the actual declaration line is reached, which prevents access errors.</p>
</li>
<li><p><strong>Understanding Scope and Scope Chain</strong> - Scope is managed through the Scope Chain, a linked structure that connects each scope to its parent scope. This is why inner functions can access outer variables, but outer functions cannot access variables declared inside inner functions.</p>
</li>
<li><p><strong>Closures Demystified</strong> - Closures are created when a function is returned from another function and retains access to its outer scope's variables, even after the outer function has been destroyed. JavaScript preserves the lexical environment in something called the Closure Scope.</p>
</li>
<li><p><strong>var vs. let vs. const</strong> - The guide clarified the key difference – <code>var</code> gets assigned <code>undefined</code> during the Creation Phase (legacy behavior from ES5), while <code>let</code> and <code>const</code> remain in the Temporal Dead Zone until their declaration is reached, making them safer and more predictable.</p>
</li>
</ol>
<h2 id="heading-final-words">Final Words</h2>
<p>I hope this comprehensive guide has helped you understand Execution Context and all the concepts connected to it. By mastering this fundamental concept, you now have the foundation to understand nearly every advanced JavaScript topic that comes your way.</p>
<p>When you encounter tricky JavaScript behaviors in the future, you can refer back to Execution Context to understand the "why" behind them. This will make you a much more effective and confident JavaScript developer.</p>
<p>Keep practicing, keep experimenting, and keep deepening your understanding of how JavaScript truly works at the engine level. Your journey to becoming a JavaScript expert has just gotten much clearer!</p>
<p>If you found the information here valuable, feel free to share it with others who might benefit from it. I’d really appreciate your thoughts – mention me on X <a target="_blank" href="https://x.com/sumit_analyzen">@sumit_analyzen</a> or on Facebook <a target="_blank" href="https://facebook.com/sumit.analyzen">@sumit.analyzen</a>, <a target="_blank" href="https://youtube.com/@logicBaseLabs">watch</a> my coding tutorials, or simply <a target="_blank" href="https://www.linkedin.com/in/sumitanalyzen/">connect with me</a> on LinkedIn. You can also checkout my official website <a target="_blank" href="http://sumitsaha.me">sumitsaha.me</a> for details about me.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Closures Work in JavaScript: A Handbook for Developers ]]>
                </title>
                <description>
                    <![CDATA[ If you're learning JavaScript, you've probably heard the term "closure" at some point. In many developers' experience, just hearing this word can trigger anxiety. In nearly 17 years of programming experience, I've noticed that closures are one of the... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-closures-work-in-javascript-a-handbook-for-developers/</link>
                <guid isPermaLink="false">6925c63dff3af82fd3477d27</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ closure ]]>
                    </category>
                
                    <category>
                        <![CDATA[ closures in javascript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sumit Saha ]]>
                </dc:creator>
                <pubDate>Fri, 16 Jan 2026 08:00:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764083198713/3afde98a-fecd-4669-a2ad-3d78c28d3d5a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're learning JavaScript, you've probably heard the term "closure" at some point. In many developers' experience, just hearing this word can trigger anxiety. In nearly 17 years of programming experience, I've noticed that closures are one of the most intimidating topics for JavaScript developers, even though they shouldn't be.</p>
<p>The main goal of this handbook is to remove that fear. By the end of this guide, you should be able to confidently say, "I’m not afraid of closures anymore!"</p>
<p>Closures aren't actually that complicated at all when you break them down. They just might seem harder to grasp while you don't understand them clearly. Many articles or tutorials don't explain the topic deeply, which leaves you confused, asking questions like, "What exactly is a closure?" or "What does it really mean?"</p>
<p>Throughout this handbook, I'll walk you through several examples step by step. If you stick with this guide until the end, I promise – all your confusion about closures should disappear.</p>
<h2 id="heading-heres-what-well-cover">Here’s What We’ll Cover</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-project-setup-before-learning-closures">Project Setup Before Learning Closures</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-create-a-new-project-folder">Create a New Project Folder</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-the-indexhtml-file">Create the index.html File</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-the-script-folder-seven-example-files">Create the script Folder + Seven Example Files</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-very-important-note">Very Important Note</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-run-the-project">Run the Project</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-functions-and-parameters-the-basics">Functions and Parameters - The Basics</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-accessing-variables-without-parameters">Accessing Variables Without Parameters</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-scope-and-lexical-scoping">Understanding Scope and Lexical Scoping</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-closure">What is a Closure?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-functions-as-objects">Functions as Objects</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-function-parent-relationship">The Function-Parent Relationship</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-nested-functions-and-closures">Nested Functions and Closures</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-refining-the-example">Refining the Example</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-creating-private-properties-with-closures">Creating Private Properties with Closures</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-role-of-closures-in-privacy">The Role of Closures in Privacy</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-closure-mechanics">Understanding Closure Mechanics</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-how-closures-make-decisions">How Closures Make Decisions</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-closures-and-enclosing-scopes">Closures and Enclosing Scopes</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-the-documentation-definition">The Documentation Definition</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-enclosing-scope-concept">The Enclosing Scope Concept</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-interpreting-the-closure-definition">Interpreting the Closure Definition</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-practical-example-self-contained-closures">Practical Example - Self-Contained Closures</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-understanding-references">Understanding References</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-the-difference-between-var-and-let">The Difference Between var and let</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-understanding-var-and-let-scoping">Understanding var and let Scoping</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-observing-the-difference">Observing the Difference</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-iife-with-let">Using IIFE with let</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-closures-through-a-practical-stopwatch-example">Understanding Closures Through a Practical Stopwatch Example</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-defining-the-stopwatch-function">Defining the Stopwatch Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-the-stopwatch">Using the Stopwatch</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-calling-the-timer-function">Calling the Timer Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-inspecting-the-timer-function">Inspecting the Timer Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-closures-and-garbage-collection">Closures and Garbage Collection</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-closures-in-asynchronous-code">Closures in Asynchronous Code</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-basic-asynchronous-example-with-settimeout">Basic Asynchronous Example with setTimeout</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-external-function-reference-example">External Function Reference Example</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-practical-example-api-requests-with-closures">Practical Example: API Requests with Closures</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-refactoring-with-external-function">Refactoring with External Function</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-advanced-example-closures-in-loops">Advanced Example - Closures in Loops</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-synchronous-loop-example">Synchronous Loop Example</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-asynchronous-loop-example">Asynchronous Loop Example</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-var-vs-let-problem">The var vs let Problem</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-consoledir-with-loop-closures">Using console.dir with Loop Closures</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-var-loop-problem">The var Loop Problem</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-fixing-the-var-loop-problem-with-iife">Fixing the var Loop Problem with IIFE</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-summary-and-key-takeaways">Summary and Key Takeaways</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-closure-1">What is a Closure?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-main-ideas-in-this-guide">The Main Ideas in This Guide</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-importance-of-closures">The Importance of Closures</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-final-words">Final Words</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along and get the most out of this guide, you should have:</p>
<ol>
<li><p>Basic JavaScript (ES6-style) knowledge</p>
</li>
<li><p>Familiarity with browser developer tools</p>
</li>
<li><p>Comfort with asynchronous code (promises)</p>
</li>
<li><p>Basic ability to use the terminal/command line</p>
</li>
<li><p>Familiarity with a code editor like VS Code – Live Server extension (for running HTML files locally)</p>
</li>
</ol>
<p>I’ve also created a video to go along with this article. If you’re the type who likes to learn from video as well as text, you can check it out below.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/JVT_d9Qx_ro" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-project-setup-before-learning-closures">Project Setup Before Learning Closures</h2>
<p>Closures are an amazing concept in JavaScript. But if you jump into the code without preparation, they can feel a bit intimidating.</p>
<p>So before we start exploring closures, let's set up a simple, clean project where you can test each example comfortably. Once this setup is done, you won't need to repeat it again and again throughout the article. So follow along carefully and you'll prepare everything at once.</p>
<h3 id="heading-create-a-new-project-folder">Create a New Project Folder</h3>
<p>Open your terminal and run:</p>
<pre><code class="lang-bash">mkdir closure
<span class="hljs-built_in">cd</span> closure
</code></pre>
<p>This folder will contain your main HTML file and all the JavaScript examples.</p>
<h3 id="heading-create-the-indexhtml-file">Create the index.html File</h3>
<p>Now create the HTML file:</p>
<pre><code class="lang-bash">touch index.html
</code></pre>
<p>Open <code>index.html</code> and add the following code:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Closure Tutorial | LogicBase Labs<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./script/example-1.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./script/example-2.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./script/example-3.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./script/example-4.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./script/example-5.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./script/example-6.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./script/example-7.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h4 id="heading-why-so-many">Why so many <code>&lt;script&gt;</code> tags?</h4>
<p>Good question! In this tutorial, you'll explore closures in <strong>7 different ways</strong>. Each example will live in its own JavaScript file, so things stay clean and beginner-friendly. If you tried to put everything inside one file, the outputs would get mixed up and confusing. That's why you're loading each example separately.</p>
<h3 id="heading-create-the-script-folder-seven-example-files">Create the <code>script</code> Folder + Seven Example Files</h3>
<p>Let's create a folder named <strong>script</strong>:</p>
<pre><code class="lang-bash">mkdir script
<span class="hljs-built_in">cd</span> script
</code></pre>
<p>Now create the seven example files:</p>
<pre><code class="lang-bash">touch example-1.js
touch example-2.js
touch example-3.js
touch example-4.js
touch example-5.js
touch example-6.js
touch example-7.js
</code></pre>
<p>You'll write and test each closure example inside these files.</p>
<h3 id="heading-very-important-note">Very Important Note:</h3>
<p>If all 7 files run at the same time, your console output will get mixed up. You won't understand which message came from which example.</p>
<p>So here's the rule:</p>
<ul>
<li><p>When working on <code>example-1.js</code>, comment out the rest.</p>
</li>
<li><p>When working on <code>example-3.js</code>, uncomment that one only, and comment out the others.</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- &lt;script src="./script/example-1.js"&gt;&lt;/script&gt; --&gt;</span>
<span class="hljs-comment">&lt;!-- &lt;script src="./script/example-2.js"&gt;&lt;/script&gt; --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./script/example-3.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-comment">&lt;!-- &lt;script src="./script/example-4.js"&gt;&lt;/script&gt; --&gt;</span>
<span class="hljs-comment">&lt;!-- &lt;script src="./script/example-5.js"&gt;&lt;/script&gt; --&gt;</span>
<span class="hljs-comment">&lt;!-- &lt;script src="./script/example-6.js"&gt;&lt;/script&gt; --&gt;</span>
<span class="hljs-comment">&lt;!-- &lt;script src="./script/example-7.js"&gt;&lt;/script&gt; --&gt;</span>
</code></pre>
<p>This keeps your output clean, clear, and conflict-free.</p>
<h3 id="heading-run-the-project">Run the Project</h3>
<p>Open <strong>Live Server</strong> from VS Code and you'll see: <a target="_blank" href="http://127.0.0.1:5500/closure/index.html">http://127.0.0.1:5500/closure/index.html</a></p>
<p>This is your working route. Inside this project, you'll explore the full world of closures step by step. Now you're ready to dive into closures and learn what they are, how they work, and why closures are one of the most powerful concepts in JavaScript.</p>
<h2 id="heading-functions-and-parameters-the-basics">Functions and Parameters – The Basics</h2>
<p>So now you will mainly work on the <code>example-1.js</code> file. Listen, throughout this entire handbook, you will first write the full code, and then we’ll go line by line to understand the breakdown in detail. There's nothing to worry about: we will uncover every single thing in its full depth.</p>
<p><strong>Full code:</strong> <code>example-1.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-1.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params">num1, num2</span>) </span>{
    <span class="hljs-keyword">return</span> num1 + num2;
}
<span class="hljs-built_in">console</span>.log(sum(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>));
</code></pre>
<p>Usually, when you want to use an outside variable inside a function, you pass it as a parameter. For example, consider a function called <code>sum</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params">num1, num2</span>)</span>
</code></pre>
<p>Here, two numbers are taken as parameters. To add these numbers and return the result:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">return</span> num1 + num2;
</code></pre>
<p>To see the output:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(sum(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>));
</code></pre>
<p>The output will be <code>5</code>. Simple, right?</p>
<h2 id="heading-accessing-variables-without-parameters">Accessing Variables Without Parameters</h2>
<p><strong>Full code:</strong> <code>example-1.js</code></p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
<span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> num1 + num2;
}

<span class="hljs-built_in">console</span>.log(sum());
</code></pre>
<p>But in JavaScript, there's a way to do the same thing without passing parameters. Let's remove the parameters from the <code>sum</code> function. Instead, you'll define two variables in the global scope:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
<span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
</code></pre>
<p>Now, when you call <code>sum()</code>, the output will still be <code>5</code>.</p>
<p>The question is: <em>“how does JavaScript do this?”</em> It seems strange, right? Inside a function, you're using variables that don't actually belong to that function – they exist outside in the wider environment where the function was created. In simple terms, the function is using variables from its parent scope.</p>
<h2 id="heading-understanding-scope-and-lexical-scoping">Understanding Scope and Lexical Scoping</h2>
<p>This concept relates to one of the most fundamental principles in JavaScript: everything from a parent is accessible to the child. If there were nested functions inside this function, even the deepest child function could access variables like <code>num1</code> and <code>num2</code> from the parent. The parent's variables are fully accessible to the child, but nothing from the child can be accessed by the parent.</p>
<p>I’ve already covered this topic in a detailed video on <strong>JavaScript Scope</strong> on the LogicBase Labs YouTube channel. If you'd like to revisit the concept or get a quick refresher, you can watch the video below.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/NtHgwL3uubk" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>For example, if you define a new variable inside the <code>sum</code> function, it cannot be accessed from outside the function. This is the core idea of scope. This system of scope is theoretically called <strong>Lexical Scoping</strong>. Since today's topic is Closures, understanding scope is essential, as closures and scope are deeply connected.</p>
<p>According to lexical scoping, a child function can access its parent's variables, but a parent cannot access the child's. This isn't random – it's a specific convention or guideline in JavaScript.</p>
<h2 id="heading-what-is-a-closure">What is a Closure?</h2>
<p>The word "closure" literally means a "bond" or "enclosure." Think of it like keeping a variable safely locked away, just like storing something inside a box.</p>
<p>Even though the box is closed, you can still use its contents when needed. This is why it's called a closure: because you keep a function's variables enclosed in such a way that, even if the outside world cannot access them directly, the function itself can still use them whenever required.</p>
<h2 id="heading-functions-as-objects">Functions as Objects</h2>
<p>In JavaScript, whenever you write a function, the function is actually treated as an object. Every function in JavaScript works as an object. Just as you can <code>console.log</code> an object to see it, you can also inspect a function.</p>
<p>Let's print our <code>sum</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.dir(sum);
</code></pre>
<p>Notice that you're not calling the function. Rather, you're just printing its body. You use <code>dir</code> instead of <code>log</code> because <code>console.log</code> only shows the function body, while <code>console.dir</code> displays the function as an object, letting you see each of its properties one by one. You can think of it as an upgraded version of <code>console.log</code>.</p>
<p>Looking at the output, you'll see an object. Expanding it reveals many properties, like <code>name</code>, <code>length</code>, <code>prototype</code>, and more. At the very bottom, there's a property called <code>Scopes</code>. Inside <code>Scopes</code>, there's a section named <code>Global</code> containing further details. The <code>Scopes</code> property is what we’ll mainly focus on here.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763460615059/210b2880-7cb7-4161-ac75-c67d196341ed.png" alt="Nested Function and Closure" width="1920" height="1080" loading="lazy"></p>
<h2 id="heading-the-function-parent-relationship">The Function-Parent Relationship</h2>
<p>Notice something here: the <code>sum</code> function has its own world, right? So why is it still referencing the global scope?</p>
<p>Every function actually maintains a connection with its parent environment. It doesn't just live in its own world – it keeps a link to the environment where it was created. Simply put, it always holds a reference to its parent.</p>
<p>Why does it do this? Because if anything changes in the parent environment (like a variable's value or the need to use it inside the function), the function can still access it.</p>
<p>This whole process is the core concept of a closure. A function keeps track of the variables it uses from outside its own scope by closing over its parent, and its parent's parent – essentially the entire scope chain above it – holds them as references.</p>
<p>That's why this example is actually the simplest form of a closure. The <code>sum</code> function itself is a closure because it has captured some variables from its outer environment and can use them whenever needed.</p>
<p>Even though you often see closures explained with examples where "a function is inside another function," the fundamental idea starts here: <em>“any function that retains access to variables from its outer scope is, in essence, a closure.”</em></p>
<h2 id="heading-nested-functions-and-closures">Nested Functions and Closures</h2>
<p><strong>Full code:</strong> <code>example-1.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-1.js</span>
<span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
<span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> num1 + num2;
    };
}

<span class="hljs-keyword">var</span> myFunc = sum();

<span class="hljs-built_in">console</span>.dir(myFunc);
</code></pre>
<p>You can understand this even more clearly by tweaking the previous <code>sum</code> function. Instead of directly returning a value, you'll have the <code>sum</code> function return another function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{};
</code></pre>
<p>And inside this inner function, you write:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">return</span> num1 + num2;
</code></pre>
<p>So what does this mean? The <code>sum</code> function is no longer returning a value directly. Instead, it's returning a function.</p>
<p>Now, create another variable called <code>myFunc</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> myFunc = sum();
</code></pre>
<p>You called the <code>sum</code> function, and whatever it returned (the inner function) is now stored in <code>myFunc</code>. In other words, <code>myFunc</code> is essentially the inner function returned by <code>sum</code>.</p>
<p>If you print <code>myFunc</code> to the console:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.dir(myFunc);
</code></pre>
<p>You'll see <code>num1</code> and <code>num2</code> listed as variables in the output. This function is still holding onto its global environment. Even though it's an inner function, it's still connected to the global scope and maintains the same global references as before.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763460615059/210b2880-7cb7-4161-ac75-c67d196341ed.png" alt="Nested Function and Closure" width="1920" height="1080" loading="lazy"></p>
<h2 id="heading-refining-the-example">Refining the Example</h2>
<p><strong>Full code:</strong> <code>example-1.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-1.js</span>
<span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> num1 + num2;
    };
}

<span class="hljs-keyword">var</span> myFunc = sum();

<span class="hljs-built_in">console</span>.dir(myFunc);
</code></pre>
<p>Now, remove the <code>num2</code> variable from the global scope and define it inside the <code>sum</code> function instead.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763463873933/84153aca-ee54-476d-99be-4b638926c0f4.gif" alt="Refine the closure" width="1138" height="640" loading="lazy"></p>
<p>This time, in the browser, you can clearly see something labeled "Closure." In other words, the browser is directly showing that a closure has been created inside this function.</p>
<p>In older versions of Chrome, you would have seen "Closure" in the previous example too. But in the newer versions, it shows as "Global" until a function actually closes over another function. When a function is returned from within another function, that's when the browser displays "Closure." But keep in mind that theoretically, the previous example was also a kind of closure. The difference is just in how the browser presents it.</p>
<p>When you did <code>console.dir(myFunc)</code>, you saw that this inner function is using both <code>num1</code> and <code>num2</code>:</p>
<ul>
<li><p><code>num1</code> is in the global scope</p>
</li>
<li><p><code>num2</code> is inside the <code>sum</code> function's scope</p>
</li>
</ul>
<p>So what is this inner function doing? It's taking a reference to <code>num1</code> from the global scope and at the same time taking a reference to <code>num2</code> from its parent function, <code>sum</code>. In other words, this inner function now carries two worlds within it: one is the global scope, and the other is its parent scope. This is exactly what a closure does: it keeps all the outer scopes it needs "enclosed" so it can use their variables whenever necessary.</p>
<p>In the browser, you can see that inside this closure, <code>num2</code> exists, while <code>num1</code> remains in the global scope. So <code>num1</code> is no longer part of the closure. What does this mean? The function only carries the parts of the environment it actually needs for its execution. Simply put, it takes all the variables it needs, along with their references, as a compact package.</p>
<p>Think of it like the function holding onto references: whenever any of these variables are updated, the function can see those changes because it's still connected to the same references.</p>
<p>If you called <code>myFunc = sum()</code> once and keep calling <code>sum()</code> repeatedly, there's no problem. Each time, a new function will create its own separate scope and keep a reference to that scope. You defined a function and then called it elsewhere. Every time you call that function, it can still access the data from its previous scope. That's because every function preserves all the information from its parent scope as references. This is exactly how a function remembers its outer variables – and this is what a closure is.</p>
<h2 id="heading-creating-private-properties-with-closures">Creating Private Properties with Closures</h2>
<p>So far, all the examples you've seen were very simple. Now, let's look at a practical example that will help you understand closures better and clear up any confusion.</p>
<p>Think about other programming languages for a minute: when you want to create a private property, what do you usually do? You define a property inside a class and mark it as "private" so that no one can access it directly from outside the class. Then, inside the class, you create one or more public functions (like getters or setters) which allow controlled access to or modification of that property. In other words, you can't touch the property directly from outside – you can only interact with it through specific functions defined inside the class.</p>
<p>In JavaScript, you can achieve the same idea much more simply using closures, entirely in a functional style.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763463928785/5e2d10bf-0e21-420d-8c27-576ab7172896.gif" alt="Creating private property" width="1138" height="640" loading="lazy"></p>
<p>How? Let's see an example. Suppose you have a simple function:</p>
<p><strong>Full code:</strong> <code>example-2.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-2.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bankAccount</span>(<span class="hljs-params">initialBalance</span>) </span>{
    <span class="hljs-keyword">var</span> balance = initialBalance;

    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> balance;
    };
}
<span class="hljs-keyword">var</span> account = bankAccount(<span class="hljs-number">100000</span>);

<span class="hljs-built_in">console</span>.log(account());
<span class="hljs-built_in">console</span>.dir(account);
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bankAccount</span>(<span class="hljs-params">initialBalance</span>) </span>{}
</code></pre>
<p>You've named it <code>bankAccount</code>, and it takes the user's initial balance as a parameter.</p>
<p>Inside it, define a variable:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> balance = initialBalance;
</code></pre>
<p>So, the user's initial balance is stored internally in a variable called <code>balance</code>. Next, return a function that returns this <code>balance</code> variable. In other words, the balance can only be accessed through this returned function.</p>
<p>Outside, in the global scope, create a variable:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> account = bankAccount(<span class="hljs-number">100000</span>);
</code></pre>
<p>Here, you called the <code>bankAccount</code> function and passed 100000 as the initial balance. What is this function actually doing? It's returning another function. So now, the <code>account</code> variable holds that returned function.</p>
<p>If you write in the console:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(account());
</code></pre>
<p>The output will be 100000.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763463963441/8104145d-b908-4131-8a6b-3c4c3ad88434.png" alt="Private Property Output" width="1920" height="1080" loading="lazy"></p>
<p>But if you try this:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(balance);
</code></pre>
<p>it won't work, because the <code>balance</code> variable cannot be accessed from outside.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763463984564/6c70013b-6566-4bf2-a517-bea3672022e1.png" alt="Error Output" width="2880" height="1800" loading="lazy"></p>
<p>What does this mean? The <code>balance</code> property is protected or private. No one from the outside can directly touch it. To see the balance, you can only call the returned function inside the original function. This is how you keep <code>balance</code> as a private variable and control access to it.</p>
<h2 id="heading-the-role-of-closures-in-privacy">The Role of Closures in Privacy</h2>
<p>So, what's the role of the closure here? It's exactly what makes this possible. The inner function is the closure. If you write:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.dir(account);
</code></pre>
<p>You'll see that inside the <code>account</code> function is the returned function.</p>
<p>By taking the output and expanding it, you'll see that the <code>balance</code> variable exists inside the closure. Exactly, right? This means that <code>balance</code> wasn't created inside the <code>account</code> function itself – it was created one scope level up. Yet, you can still access <code>balance</code> from the returned function.</p>
<p>It's similar to the previous example, but this use case is slightly different. Here, you're showing how a private property can be kept secure. Even though you called the inner function from the outside, it still had access to <code>balance</code> within its scope. So, the outer scope cannot directly access <code>balance</code>, but thanks to the closure, you can maintain a reference to it. Even though the function is called from outside, the closure allows you to access the private property in a protected way.</p>
<p>Why protected? Because you're not accessing it directly – you can only see <code>balance</code> through the function call.</p>
<p>💡This is another powerful use case of closures: securing private properties so that they can't be directly accessed from outside, but only through specific functions.</p>
<h2 id="heading-understanding-closure-mechanics">Understanding Closure Mechanics</h2>
<h3 id="heading-how-closures-make-decisions">How Closures Make Decisions</h3>
<p>Now, let’s look at another aspect of closures. We’ll revisit our first example.</p>
<p><strong>Previous code:</strong> <code>example-1.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-1.js</span>
<span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> num1 + num2;
    };
}

<span class="hljs-keyword">var</span> myFunc = sum();

<span class="hljs-built_in">console</span>.dir(myFunc);
</code></pre>
<p>In that example, you used a variable called <code>num2</code> inside the inner function. That's why the function acted as a closure, right?</p>
<p><strong>Full code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
<span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> num1;
    };
}
<span class="hljs-keyword">var</span> myFunc = sum();
<span class="hljs-built_in">console</span>.dir(myFunc);
</code></pre>
<p>Now, keep the variable but stop using <code>num2</code> inside the inner function. If you check the output, you'll see that the closure is gone. Why?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464099671/a34e465a-ed85-4631-8a0d-07e681cecc52.png" alt="Closure Gone Output" width="1920" height="1080" loading="lazy"></p>
<p>It's because <code>num2</code> isn't used inside the inner function. JavaScript smartly recognizes that this variable isn't needed, so it's not included in the closure. In other words, JavaScript decides on its own: variables that won't be used inside the function, even if they exist in the outer scope, are not included in the closure. Only the variables that the function actually needs become part of the closure.</p>
<p><strong>Full code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
<span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
    <span class="hljs-keyword">var</span> num = <span class="hljs-number">6</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> num;
    };
}
<span class="hljs-keyword">var</span> myFunc = sum();
<span class="hljs-built_in">console</span>.dir(myFunc);
</code></pre>
<p>For example, if you define another variable inside the <code>sum</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> num = <span class="hljs-number">6</span>;
</code></pre>
<p>and do nothing else, there's still no need for a closure. But if you modify the inner function to return <code>num</code> instead of <code>num1</code>, the closure appears again. This time, the closure contains only <code>num</code>. <code>num2</code> won't be there, but <code>num1</code> remains because it exists in the global scope. JavaScript preserves this scope to maintain lexical scoping.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464124937/3a155661-838d-4070-a8ab-e6c283a0838f.png" alt="Closure with num Output" width="2560" height="1440" loading="lazy"></p>
<p>If you look at the global scope, you can still see <code>num1</code>. That's because you used the <code>var</code> keyword. If you had used <code>let</code>, it wouldn't be visible. The key difference you're noticing is: <code>num1</code> exists in the global scope, so it remains in the closure's "environment," but if a variable inside the inner function isn't used, it's not included in the closure.</p>
<p>For example, if you use <code>num1</code>, you're accessing the global variable. So what happens now? Will there be a closure? Look, there isn't one. Since <code>num1</code> exists in the global scope, there's no extra need. The global scope is sufficient, and no separate closure is required. This shows how closures actually work.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464145498/68d704f4-f614-49e9-929f-735880ef374a.png" alt="No Closure with Global Output" width="2560" height="1440" loading="lazy"></p>
<p>A closure decides which variables need to be kept inside the function and which don't. JavaScript makes this decision automatically. You just need to remember lexical scoping so that outer scope variables can be accessed.</p>
<p>In simple terms, closures make intelligent decisions. Variables used inside the function are kept "inside," variables in outer scopes that aren't used aren't included, and global variables are accessible directly, so there's no need to include them in the closure.</p>
<p>So here, you kept <code>num1</code>, and it exists in the global scope. The function can access it directly from there. But if the inner function used only <code>num</code> – which doesn't exist in its own scope or globally – then a closure would have to be created to carry that variable along.</p>
<p>In short, a closure doesn't wrap everything. It doesn't include variables that are already outside. This is an important point. Another important point is that global scope variables are never included in closures.</p>
<h2 id="heading-closures-and-enclosing-scopes">Closures and Enclosing Scopes</h2>
<h3 id="heading-the-documentation-definition">The Documentation Definition</h3>
<p>Often, there's some confusion about when a closure appears and when it just shows global. Even senior interviewers sometimes hesitate to call the global scope a closure at first glance.</p>
<p>If you look at the JavaScript documentation maintained by Mozilla, the 2016 docs highlighted something important.</p>
<p>In the definition, it stated:</p>
<blockquote>
<p>"variables that are used locally, but defined in an enclosing scope" (<a target="_blank" href="https://web.archive.org/web/20160722004334/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures">Reference</a>)</p>
</blockquote>
<p>This refers to variables that are used locally inside a function but are actually defined in an outer scope. This is key. Only variables that are actually used inside a function are included in the closure. Variables that exist in an outer scope but aren't used inside the function aren't part of the closure.</p>
<p>In simple terms, a closure is a function that remembers its local scope along with the necessary variables from an outer scope, so even if the function is called from outside, it can still access those variables.</p>
<h3 id="heading-the-enclosing-scope-concept">The Enclosing Scope Concept</h3>
<p>Suppose you have a variable <code>num</code> defined outside, but you use it locally inside the function. That's why the browser shows it as a closure, just like the documentation says.</p>
<p><strong>Full Code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
<span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
    <span class="hljs-keyword">return</span> num1 + num2;
}
<span class="hljs-built_in">console</span>.dir(sum);
</code></pre>
<p>But if you don't use the outer variable inside the returned function, what happens? If you removed everything else and just returned <code>num1 + num2</code>, the <code>sum</code> function would work fine. But if you do <code>console.dir(sum)</code>, the word "closure" doesn't appear.</p>
<p>Why? Because <code>num2</code> is local inside the function, and there's no need to include it in a closure. A closure is only needed to use variables from an outer scope. Since this is the very first-level outer scope (meaning the global scope) and it's not inside any function, the <code>sum</code> function is already capturing it in its own scope. So no additional closure is created.</p>
<p>The critical question is: <em>“when does the browser show a closure, and when doesn't it?”</em> The explanation comes from the documentation: "variables that are used locally, but defined in an enclosing scope." Your <code>num1</code> variable is defined outside but used locally inside. But <code>num1</code> doesn't have any enclosing scope. Here, an enclosing scope means a scope that wraps around another scope – inside a set of brackets. But <code>num1</code> is directly in the global scope, not inside any enclosing scope.</p>
<p><strong>Full code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
        <span class="hljs-keyword">return</span> num1 + num2;
    }

    <span class="hljs-built_in">console</span>.dir(sum);
})();
</code></pre>
<p>If you want to bring this into an enclosing scope, you need to wrap the whole thing inside a function. You can write an anonymous function like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{}
</code></pre>
<p>Then you put everything inside that function and immediately call it. This is known as an <strong>Immediately Invoked Function Expression</strong> (IIFE for short). It’s basically a function that gets defined and executed at the same time.</p>
<p>When you use an IIFE, everything gets moved into an enclosing scope. The <code>num1</code> that was previously open in the global scope is now inside this function. So it's now part of an enclosing scope. If you check in the browser and expand it, you see the word "closure."</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464214402/43092c54-012f-42be-a7ea-d25c4d15eb90.png" alt="Closure with Enclosing Scope Output" width="2560" height="1440" loading="lazy"></p>
<p>That's because you've brought the variables into an enclosing scope. The browser now shows it as a closure.</p>
<h3 id="heading-interpreting-the-closure-definition">Interpreting the Closure Definition</h3>
<p>If someone ever gets confused or disagrees, they might say, "The outer one isn't a closure, it's just the global scope." But theoretically, you can still consider it a closure. Some might insist, "That's a closure," while others may not agree.</p>
<p>The thing is, JavaScript always keeps the global scope intact to maintain lexical scoping. People who disagree might say, "The global scope is just preserved, that's not a closure." And that's fair. But the concept is really the same. If a variable from an outer scope is used or referenced inside a function, it behaves just like a closure. The idea is consistent.</p>
<p>There's a small difference though: the global scope keeps all variables that exist outside any function. That's why some might argue it's not technically a closure. But from a theoretical perspective, it behaves like one, with only minor differences for global variables.</p>
<p><strong>Full code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
<span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
    <span class="hljs-keyword">return</span> num1 + num2;
}

<span class="hljs-built_in">console</span>.dir(sum);
</code></pre>
<p>If you didn't use an IIFE and went back to the previous setup, the browser would no longer show it as a closure. And the <code>var num1</code> is in the global scope.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464280818/d25cc856-0178-4d94-9f56-654f4c62637d.png" alt="No Closure with Global Output" width="2560" height="1440" loading="lazy"></p>
<p>If you add another variable:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> num3 = <span class="hljs-number">5</span>;
</code></pre>
<p>This <code>num3</code> isn't used by the <code>sum</code> function, but if you look in the global scope, you can still see it. The browser shows <code>num3</code> as well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464328789/6bcffff2-3e8c-4cc7-8da6-9f03910aee92.png" alt="Global Scope with num3 Output" width="2560" height="1440" loading="lazy"></p>
<p>But a closure only keeps what's necessary. Here, <code>num3</code> exists because it's part of the global scope. The global object always holds references to its own variables, which is why <code>num3</code> is visible. This often causes confusion: should you call it a closure or not?</p>
<p>The point is, in the 2016 documentation, the term "enclosing scope" was clearly mentioned. In the current documentation, that phrase is missing. This means they've intentionally avoided that confusion.</p>
<p>The modern definition now says, "closure is the combination of a function bundled together with references to its surrounding state" which is written more concisely compared to before. (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures">Reference</a>)</p>
<p>Here, "state" refers to the lexical environment – that could be the child's environment, the parent's environment, or the entire scope. Based on this definition, a function keeps itself along with any variables it needs to remember, all bundled together. Explaining this clearly in words can be tricky. But you'll see more examples ahead, which will make each use case clear.</p>
<h2 id="heading-practical-example-self-contained-closures">Practical Example: Self-Contained Closures</h2>
<p><strong>Full code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
    <span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> num1 + num2;
    }

    <span class="hljs-built_in">console</span>.log(sum());
    <span class="hljs-built_in">console</span>.dir(sum);
})();
</code></pre>
<p>Let's look at another aspect. You're going back to the IIFE function. Here, you have a function called <code>sum</code> that adds <code>num1</code> and <code>num2</code> and returns the result. Both <code>num1</code> and <code>num2</code> exist inside the IIFE function. This means you've kept the whole setup self-contained within a closure function.</p>
<p>When you call the <code>sum</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(sum());
</code></pre>
<p>and on the next line write:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.dir(sum);
</code></pre>
<p>Check the output. Initially, <code>2 + 3</code> gives <code>5</code>, which is exactly what you see. Since <code>num1</code> and <code>num2</code> now exist inside the global scope of the IIFE.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464361079/cdcff658-023c-4a25-8749-eb618b3cfcc3.png" alt="IIFE Closure Output" width="2560" height="1440" loading="lazy"></p>
<p><strong>Full code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
    <span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> num1 + num2;
    }
    <span class="hljs-built_in">console</span>.log(sum());
    <span class="hljs-built_in">console</span>.dir(sum);

    num1 = <span class="hljs-number">6</span>;
    num2 = <span class="hljs-number">7</span>;

    <span class="hljs-built_in">console</span>.log(sum());
    <span class="hljs-built_in">console</span>.dir(sum);
})();
</code></pre>
<p>You can modify these variables if you want:</p>
<pre><code class="lang-javascript">num1 = <span class="hljs-number">6</span>;
num2 = <span class="hljs-number">7</span>;
</code></pre>
<p>Then if you call again:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(sum());
<span class="hljs-built_in">console</span>.dir(sum);
</code></pre>
<p>You'll see two different results. The first call returns <code>5</code> because initially <code>2 + 3</code> was calculated. After changing <code>num1</code> and <code>num2</code>, the next call returns <code>13</code>. So, you can see that a closure keeps hold of the outer variables and makes them accessible inside the function, right?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464386404/cd2447c8-447e-4fff-b72d-f6ec2d2c8122.png" alt="IIFE Closure with Updated Values Output" width="2560" height="1440" loading="lazy"></p>
<p>Now, at that moment, you checked the function using <code>console.dir</code>. First, expand the <code>dir</code> at the bottom. Here, you see an entry labeled "closure," and inside it, you notice <code>num1 = 6</code> and <code>num2 = 7</code>. Great, because before writing <code>dir</code>, you had changed the values of <code>num1</code> and <code>num2</code>, so it's showing the latest values. But if you go back to the previous state and expand the first <code>console.dir</code>, surprisingly, it still shows <code>num1 = 6</code> and <code>num2 = 7</code>. Both are the same – pretty weird, isn't it?</p>
<p>This is because when you did <code>console.log</code>, the result showed <code>2 + 3</code>. But in the very next line, the values hadn't actually changed yet. In <code>console.dir</code>, you see that inside the closure, the values remain 6 and 7.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464426043/f7f87ffb-8bf5-4fbb-ac1c-091bee65570c.gif" alt="Closure with Updated Values Dir Output" width="1138" height="640" loading="lazy"></p>
<p>This is exactly what I’ve been emphasizing: <strong>a closure doesn't really hold the values themselves. It holds a reference to the variables.</strong></p>
<h3 id="heading-understanding-references">Understanding References</h3>
<p>So, what does this mean? It means that there's a pointer stored to the memory location of your variable. Once a reference is stored, the pointer itself stays the same, but the value can change anytime.</p>
<p>When you use <code>console.dir</code>, the browser is showing that reference, which is why it always displays the latest value. The browser works very fast, and the reference has already been updated. When you set <code>num1</code> and <code>num2</code> to 6 and 7 inside the closure, the reference gets updated. You're seeing the exact same variable, but you don't see the intermediate values. But when you do <code>console.log</code>, the function uses its corresponding value correctly. That's why not every change in the intermediate scope is clearly visible. Because of reference updates, you always see the latest value, not the direct intermediate state.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464448552/b61bc77c-2563-4fb0-9630-d36a4f304439.png" alt="Closure Reference Output" width="2560" height="1440" loading="lazy"></p>
<p>So, to reiterate: a closure doesn't store the actual values inside. It stores references to those values.</p>
<p>Keeping this concept in mind is really crucial.</p>
<h2 id="heading-the-difference-between-var-and-let">The Difference Between <code>var</code> and <code>let</code></h2>
<p><strong>Full code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
<span class="hljs-keyword">var</span> num1 = <span class="hljs-number">2</span>;
<span class="hljs-keyword">var</span> num2 = <span class="hljs-number">3</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> num1 + num2;
}

<span class="hljs-built_in">console</span>.dir(sum);
</code></pre>
<p>Now, let's look at another aspect of closures. Earlier, you declared two variables in the global scope: <code>num1</code> and <code>num2</code>. So far, you've been using the <code>var</code> keyword. If you don't put anything inside an IIFE and just stay in the global scope, you won't see any closure in the browser.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464484448/99a70a30-f07f-469d-a592-59f3ed5f193c.png" alt="No Closure In Global Output" width="2560" height="1440" loading="lazy"></p>
<p>But where do <code>num1</code> and <code>num2</code> live? Well, in the global scope. That's why you write <code>console.dir(sum)</code>. In the browser, you can see <code>num1</code> and <code>num2</code> inside the global object.</p>
<p>Here's the interesting part: what happens if you replace these <code>var</code> keywords with <code>let</code>?</p>
<h3 id="heading-understanding-var-and-let-scoping">Understanding <code>var</code> and <code>let</code> Scoping</h3>
<p><strong>Full code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
<span class="hljs-keyword">let</span> num1 = <span class="hljs-number">2</span>;
<span class="hljs-keyword">let</span> num2 = <span class="hljs-number">3</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> num1 + num2;
}

<span class="hljs-built_in">console</span>.log(sum());

<span class="hljs-built_in">console</span>.dir(sum);
</code></pre>
<p>This is where the difference between <code>var</code> and <code>let</code> comes in. Many people think they're the same, but in JavaScript, <code>var</code> and <code>let</code> are not equal.</p>
<p>Simply put:</p>
<ul>
<li><p><code>var</code> is the old JavaScript declaration, and it's function-scoped. A variable declared with <code>var</code> only lives inside the function it's defined in. If it's defined outside any function, it goes to the global scope.</p>
</li>
<li><p><code>let</code> is the new ES6 declaration, and it's block-scoped. A variable declared with <code>let</code> only exists within the block or scope where it was defined and cannot be accessed from outside.</p>
</li>
</ul>
<p>One important difference is hoisting. Variables declared with <code>var</code> are hoisted, meaning JavaScript moves the declaration to the top, but the initialization doesn't happen. So if you use a <code>var</code> before it's declared, you'll get <code>undefined</code>. With <code>let</code>, even though it's hoisted, the <a target="_blank" href="https://www.freecodecamp.org/news/javascript-temporal-dead-zone-and-hoisting-explained/">temporal dead zone</a> ensures that using it before declaration throws an error.</p>
<h3 id="heading-observing-the-difference">Observing the Difference</h3>
<p>Let's see what happens if you declare the variable with <code>let</code>. Last time, when it was just in the global scope, you could see the variables when you did <code>console.dir</code>. Now, though, you see a new object named <code>script</code> has appeared, and <code>num1</code> and <code>num2</code> are no longer in the global scope.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464511845/d627b15b-8d03-48e2-ae11-3e3516cc760e.png" alt="Let Scope Output" width="2880" height="1800" loading="lazy"></p>
<p>Why is that? It's because of the difference between <code>let</code> and <code>var</code> that you talked about earlier. <code>let</code> is block-scoped, while <code>var</code> is function-scoped. If you treat the outer context as a main function, a variable declared with <code>var</code> becomes part of the global scope. But with <code>let</code>, it stays within its block scope and doesn't directly become part of the global object. So <code>let</code> actually lives inside a separate object called <code>script</code> and not in the global scope.</p>
<p>Understanding this is really important, because if you’re following along with this handbook and you’re trying to print variables while using <code>let</code> out of habit, the output won't be like it is with <code>var</code>. This can definitely be confusing. Simply put, <code>let</code> doesn't go into the global object. It exists inside a separate <code>script</code> object.</p>
<h3 id="heading-using-iife-with-let">Using IIFE with <code>let</code></h3>
<p><strong>Full code:</strong> <code>example-3.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-3.js</span>
(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> num1 = <span class="hljs-number">2</span>;
    <span class="hljs-keyword">let</span> num2 = <span class="hljs-number">3</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> num1 + num2;
    }

    <span class="hljs-built_in">console</span>.dir(sum);
})();
</code></pre>
<p>But what if you wrap the whole thing in an enclosing function again, like before with an IIFE? When you check the output now, everything goes back inside its closure.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464534468/13f0579b-0476-47b4-a4b3-2d894b0e1570.png" alt="Closure with Let in IIFE Output" width="2560" height="1440" loading="lazy"></p>
<p>Ultimately, the concept of closures remains the same: what changes is whether the variable goes into <code>var</code> or <code>let</code> scope.</p>
<p>Now the situation becomes a bit simpler. You have a function, and it's in its end-closing state. According to the definition of a closure, the inner function of this function is using the outer variable <code>num1</code>. So, this inner function definitely needs a closure. That closure comes from exactly this function.</p>
<p>JavaScript creates the closure and packages <code>num1</code> inside it. The outer global world always exists separately, of course. Also remember, when using <code>console.dir</code> in the browser, the output will look different depending on whether you're dealing with <code>let</code> or <code>var</code>.</p>
<h2 id="heading-understanding-closures-through-a-practical-stopwatch-example">Understanding Closures Through a Practical Stopwatch Example</h2>
<p>So far, all the examples you've seen were very simple. Now, let's look at a practical example that will help you understand closures better and clear up any confusion.</p>
<p><strong>Full code:</strong> <code>example-4.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-4.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stopWatch</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> startTime = <span class="hljs-built_in">Date</span>.now();

    <span class="hljs-keyword">var</span> getDelay = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Date</span>.now() - startTime);
    };
    <span class="hljs-keyword">return</span> getDelay;
}

<span class="hljs-keyword">var</span> timer = stopWatch();

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">100000000</span>; i++) {
    <span class="hljs-keyword">var</span> a = <span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">1000000</span>;
}

timer();
</code></pre>
<h3 id="heading-defining-the-stopwatch-function">Defining the Stopwatch Function</h3>
<p>Let's define a function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stopWatch</span>(<span class="hljs-params"></span>) </span>{}
</code></pre>
<p>You've named it <code>stopWatch</code>, and it works just like a real stopwatch. Just like when you start a stopwatch, wait for a while, and then stop it to get the elapsed time, this function will do the same.</p>
<p>First, write:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> startTime = <span class="hljs-built_in">Date</span>.now();
</code></pre>
<p>This stores the current time in <code>startTime</code>. Then, inside the function, define:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> getDelay = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{};
</code></pre>
<p>Create a <code>getDelay</code> function, which will log the elapsed time to the console. For that, write:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Date</span>.now() - startTime);
</code></pre>
<p>Here, the elapsed time is calculated by subtracting <code>startTime</code> from the current time. Finally, simply return this <code>getDelay</code> function. The <code>stopWatch</code> function does just one thing: when you call <code>stopWatch</code>, it starts a stopwatch using <code>Date.now()</code> and returns a <code>getDelay</code> function. When you call that <code>getDelay</code> function, it shows the elapsed time from the start time to the current moment.</p>
<h3 id="heading-using-the-stopwatch">Using the Stopwatch</h3>
<p>Now, call it. Write:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> timer = stopWatch();
</code></pre>
<p>Here, you've started the <code>stopWatch</code>. This function executes, which means <code>startTime</code> is set and the <code>getDelay</code> function is defined. Then, <code>stopWatch</code> returns that <code>getDelay</code> function. The <code>stopWatch</code> function itself isn't called directly afterward – you simply called it once, and the outer function returns the <code>getDelay</code> function. Store this returned function in <code>timer</code>.</p>
<p>At this point, the <code>stopWatch</code> is already running because you called it, but you haven't printed anything from <code>getDelay</code> yet. Before calling <code>getDelay</code>, create a fake delay like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">100000000</span>; i++) {}
</code></pre>
<p>Use a large for-loop to waste some time. You chose a big number intentionally so it takes a noticeable delay. If you want, you can also perform some expensive operations in the loop, like calculating a random number:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> a = <span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">1000000</span>;
</code></pre>
<p>This way, you create a fake delay.</p>
<h3 id="heading-calling-the-timer-function">Calling the Timer Function</h3>
<p>Now, we come to <code>timer</code>. <code>Timer</code> is actually a function because it was returned by calling <code>stopWatch</code>. This returned <code>getDelay</code> function acts as your actual timer. Let’s call <code>timer()</code> and see what happens. The output doesn't appear instantly – it takes a moment, and then it shows up. So you get a delay.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464566077/f4a450a5-796b-4999-97cb-1e697afbbcfa.gif" alt="Stopwatch Output" width="1138" height="640" loading="lazy"></p>
<p>The question is: how is this still working? The <code>stopWatch</code> function, where you initially called it, has already finished executing. That means everything inside that function should be gone.</p>
<p>So how does <code>timer()</code> still know the value of <code>startTime</code>? Especially after you added such a long delay before calling it? This means the <code>timer</code> function still remembers its parent function – specifically, the <code>startTime</code> variable inside <code>stopWatch</code>. It holds onto that reference.</p>
<p>How? Because of a closure. When <code>getDelay</code> was created, a closure was also created inside it that kept track of the <code>startTime</code> variable. So even after the delay, and even after a long time, it can still use that old value. This shows that JavaScript is really smart. It tracks all variables, references, and closures, and when needed, it can use them again. This is why this behavior is possible: because of closures.</p>
<h3 id="heading-inspecting-the-timer-function">Inspecting the Timer Function</h3>
<p><strong>Full code:</strong> <code>example-4.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-4.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stopWatch</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> startTime = <span class="hljs-built_in">Date</span>.now();
    <span class="hljs-keyword">var</span> getDelay = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Date</span>.now() - startTime);
    };
    <span class="hljs-keyword">return</span> getDelay;
}

<span class="hljs-keyword">var</span> timer = stopWatch();

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">100000000</span>; i++) {
    <span class="hljs-keyword">var</span> a = <span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">1000000</span>;
}

timer();

<span class="hljs-built_in">console</span>.dir(timer);
</code></pre>
<p>If you do:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.dir(timer);
</code></pre>
<p>like before and check the output in the browser, you'll notice it takes some time to appear because of the delay. But even after the delay, it still retains <code>startTime</code> inside the closure.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464588970/1dcb2502-4989-447f-9c4c-09056c948243.png" alt="Timer Closure Output" width="2560" height="1440" loading="lazy"></p>
<p>If you try:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(startTime);
</code></pre>
<p>you won't be able to access <code>startTime</code> directly. But since <code>timer</code> is a member function, it can use that <code>startTime</code> you initialized long ago, before the for-loop. It still remembers <code>startTime</code>. No matter how long the delay, it can keep track. Even if there were more lines of code or more expensive operations during the delay, at the end of the day, when you call the timer, the closure ensures that <code>startTime</code> is correctly preserved.</p>
<p>This is one of the more fascinating aspects of JavaScript: it can really remember such information, and this is one of the biggest use cases of closures.</p>
<h3 id="heading-closures-and-garbage-collection">Closures and Garbage Collection</h3>
<p>This is one of the most powerful features of closures. Because of closures, no matter how many times you call the <code>timer()</code> function, each call works independently and keeps its own reference. Every time, a new reference is created and held as long as it's needed.</p>
<p>Let's consider a small example – but imagine in a large application, there could be countless closures holding references to many variables. Naturally, the question arises: if so many things are being remembered, will performance suffer?</p>
<p>This is where JavaScript's performance optimization comes in. <strong>JavaScript is a smart, garbage-collected language.</strong> That means when JavaScript realizes that a reference or variable is no longer needed, it automatically removes it from memory.</p>
<p>In some situations, programmers can manually optimize. For example, if you created a timer holding a reference to a <code>getDelay()</code> function, but you haven't called <code>getDelay()</code> yet, JavaScript doesn't know if it will be used in the future, so it keeps the reference.</p>
<p><strong>Full code:</strong> <code>example-4.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-4.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stopWatch</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> startTime = <span class="hljs-built_in">Date</span>.now();

    <span class="hljs-keyword">var</span> getDelay = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Date</span>.now() - startTime);
    };
    <span class="hljs-keyword">return</span> getDelay;
}

<span class="hljs-keyword">var</span> timer = stopWatch();

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">100000000</span>; i++) {
    <span class="hljs-keyword">var</span> a = <span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">1000000</span>;
}

timer();

<span class="hljs-built_in">console</span>.dir(timer);
timer = <span class="hljs-literal">null</span>;

timer();
</code></pre>
<p>If you're certain it won't be used anymore, you can manually clear the reference by writing:</p>
<pre><code class="lang-javascript">timer = <span class="hljs-literal">null</span>;
</code></pre>
<p>Now, <code>timer()</code> won't work because you set it to null. JavaScript understands that it's no longer needed and garbage collects the reference from memory. If you try this in the browser, you'll see an error: "TypeError: timer is not a function" – because <code>timer</code> is now null.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464662207/267dbda0-31c0-47b3-9df8-a6b18c04b317.png" alt="Timer Null Error Output" width="2560" height="1440" loading="lazy"></p>
<p>Simply put, setting <code>timer = null</code> tells JavaScript, "This variable won't be used anymore, forget it." The Garbage Collector then recognizes that there are no references and quietly removes it from memory, preventing memory waste.</p>
<p>The interesting part is that JavaScript doesn't just run the code – it predicts a lot even before compilation. When it sees <code>timer = null</code>, it already knows, "Okay, the programmer used this timer only this much, and it won't be needed anymore." So as soon as the code finishes running, it intelligently cleans up the memory.</p>
<p>This makes your program automatically optimized. There are no memory leaks, browser load decreases, and JavaScript executes faster. This is a very small example, but it already shows how elegantly you can manage performance in JavaScript.</p>
<h2 id="heading-closures-in-asynchronous-code">Closures in Asynchronous Code</h2>
<p>So far, all the examples you've seen were using closures in a synchronous way. Now, many people might wonder, "Okay, but how do closures work in asynchronous situations?"</p>
<p>That's a very good question. In real-world coding, most tasks run asynchronously – like with <code>setTimeout</code>, <code>fetch</code>, or event listener functions. The key point is, synchronous code executes line by line, but asynchronous code takes some time to complete. That means you call a function, but its result arrives a little later.</p>
<p>So the question is: if the outer scope has already finished by then, how does the inner function still remember the values of the outer variables?</p>
<p><strong>This is exactly where the true power of closures comes in.</strong> A closure keeps the reference to the outer scope as long as the inner function hasn't executed yet. That means whether the code is synchronous or asynchronous, closures work the same way.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464732632/3d49dab4-4b0e-4f58-9923-fe5dae876915.gif" alt="Asynchronous Closures" width="1138" height="640" loading="lazy"></p>
<h3 id="heading-basic-asynchronous-example-with-settimeout">Basic Asynchronous Example with <code>setTimeout</code></h3>
<p><strong>Full code:</strong> <code>example-5.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-5.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">asyncExample</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> a = <span class="hljs-number">20</span>;

    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(a);
    }, <span class="hljs-number">3000</span>);
}

asyncExample();
</code></pre>
<p>Now let’s see a small asynchronous example to understand how closures work and why they are just as reliable in asynchronous scenarios.</p>
<p>Define a function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">asyncExample</span>(<span class="hljs-params"></span>) </span>{}
</code></pre>
<p>Inside this function, write:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> a = <span class="hljs-number">20</span>;
</code></pre>
<p>You've defined a variable. Next, use JavaScript's built-in <code>setTimeout</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{});
</code></pre>
<p><code>setTimeout</code> takes two parameters: one is the function to run, and the other is the time in milliseconds, meaning it will call that function after the specified delay.</p>
<p>Now, suppose you put <code>console.log(a)</code> inside that function. Surprisingly, even though <code>a</code> isn't defined inside the timeout function, it can still access the <code>a</code> from <code>asyncExample</code>'s outer scope. This is possible because of closures. After 3 seconds, it appears, and you see <code>20</code>. This is also possible because of closures. The function inside <code>setTimeout</code> doesn't have <code>a</code> defined within itself, yet it can access <code>a</code> from <code>asyncExample</code>'s scope.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464763043/0d51130c-3299-49c1-bab9-6cac74b215ab.png" alt="Asynchronous Closure Output" width="2560" height="1440" loading="lazy"></p>
<h3 id="heading-external-function-reference-example">External Function Reference Example</h3>
<p><strong>Full code:</strong> <code>example-5.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-5.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">asyncExample</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> a = <span class="hljs-number">20</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myFunc</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(a);
    }

    <span class="hljs-built_in">setTimeout</span>(myFunc, <span class="hljs-number">3000</span>);
    <span class="hljs-built_in">console</span>.dir(myFunc);
}

asyncExample();
</code></pre>
<p>Now, what if you define the <code>setTimeout</code> function outside <code>asyncExample</code>, just for demonstration – like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myFunc</span>(<span class="hljs-params"></span>) </span>{}
</code></pre>
<p>Inside <code>myFunc</code>, write:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(a);
</code></pre>
<p>Then pass <code>myFunc</code> into <code>setTimeout</code> and also write:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.dir(myFunc);
</code></pre>
<p>If you check the output of <code>console.dir</code>, you'll see that inside <code>myFunc</code>, the closure contains the variable <code>a=20</code>. This is because <code>a</code> was part of <code>asyncExample</code>'s scope, so <code>myFunc</code> can still access it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464809847/359fc698-cc18-4e41-beb7-e3b7148accc1.png" alt="Asynchronous Closure with External Function Output" width="2560" height="1440" loading="lazy"></p>
<p>Just like before, this is possible thanks to closures. But here, there's a subtle difference. Earlier, you talked about a reference example, but this reference works a little differently.</p>
<p><strong>Full code:</strong> <code>example-5.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-5.js</span>

<span class="hljs-keyword">var</span> a = <span class="hljs-number">20</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">asyncExample</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myFunc</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(a);
    }

    <span class="hljs-built_in">setTimeout</span>(myFunc, <span class="hljs-number">3000</span>);
    <span class="hljs-built_in">console</span>.dir(myFunc);
}

asyncExample();

a = <span class="hljs-number">30</span>;
</code></pre>
<p>Suppose the variable <code>a=20</code> was originally inside <code>asyncExample</code>. Now, if you move <code>a</code> to the global scope and write:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> a = <span class="hljs-number">20</span>;
</code></pre>
<p>In simple terms, you've defined it outside. Now, the closure won't show it, because it's part of the global scope. <code>a</code> will just exist in the global scope with a value of <code>20</code>. You call the <code>asyncExample</code> function, which starts the <code>setTimeout</code> timer. Then, on the next line after calling <code>asyncExample</code>, you change the value of <code>a</code>:</p>
<pre><code class="lang-javascript">a = <span class="hljs-number">30</span>;
</code></pre>
<p>Now think: if <code>myFunc</code> is called as the callback for <code>setTimeout</code> and does <code>console.log(a)</code>, what value will it show? If you check the output, it will show <code>30</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464836227/3d4cc9aa-cd26-4026-bc14-2d0b980bc333.png" alt="Global Variable Asynchronous Closure Output" width="2560" height="1440" loading="lazy"></p>
<p>What does this mean?</p>
<p>When <code>asyncExample</code> is called, the <code>setTimeout</code> starts and <code>myFunc</code> is ready as the callback. Inside <code>myFunc</code>, you have <code>console.log(a)</code>. At that moment, <code>a</code> was <code>20</code> in its parent scope. But since <code>a</code> is now global and its value has been changed from outside, when the callback executes, it shows <code>30</code>.</p>
<p>This demonstrates that <strong>closures actually hold a reference to the variable.</strong> If the variable is global, any external changes are also tracked. So if you expand the global <code>a</code> in the console, you'll see <code>a = 30</code>.</p>
<p>I mentioned earlier that closures keep a reference to the value. So when <code>setTimeout</code> sends the callback to the main thread after 3 seconds, <code>myFunc</code> can still access that reference. Remember, <code>myFunc</code> comes back via <code>setTimeout</code> from another place – it doesn't run directly on the main thread. This is part of asynchronous JavaScript.</p>
<p>The function is called in the main thread after returning from the Web API, but it still retains the reference to <code>a</code>. Since <code>a</code> has been changed globally, when <code>myFunc</code> prints it, it shows the new value <code>30</code>.</p>
<p>This point is very important. Practicing multiple examples will help you better understand how closures track outer variables in asynchronous situations. This is why you need to be careful when using global variables and <code>var</code>.</p>
<p>This is also the reason <code>var</code> can sometimes cause conflicts, and why the <code>let</code> keyword was introduced. For example, if you define <code>var a</code> globally and later change <code>a</code> somewhere in the program, any asynchronous functions referencing <code>a</code> will use the new value. That's why using <code>var</code> with <code>setTimeout</code> or other asynchronous functions can lead to such issues.</p>
<p>💡An important point is that a closure doesn't keep the entire variable from its parent scope. It only keeps a reference to that variable.</p>
<h2 id="heading-practical-example-api-requests-with-closures">Practical Example: API Requests with Closures</h2>
<p>Now, let’s see another practical example of closures. In typical JavaScript applications, you often make AJAX requests to fetch data from an API URL. We’ll see how closures are used in this context. For API requests like this, JavaScript's built-in <code>fetch</code> function can be used, though third-party libraries like <code>axios</code> or <code>jQuery AJAX</code> can also accomplish the same task.</p>
<p><strong>Full code:</strong> <code>example-6.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-6.js</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">apiFunction</span>(<span class="hljs-params">url</span>) </span>{
    fetch(url).then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(res);
    });
}

apiFunction(<span class="hljs-string">"https://jsonplaceholder.typicode.com/todos/1"</span>);
</code></pre>
<p>Here, we’ll use <code>fetch</code> for a practical example. First, write a function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">apiFunction</span>(<span class="hljs-params">url</span>) </span>{}
</code></pre>
<p>You've named it <code>apiFunction</code> and gave it a parameter called <code>url</code>. This function will send a request to that URL. Then you call the built-in <code>fetch</code> function:</p>
<pre><code class="lang-javascript">fetch(url);
</code></pre>
<p>So what does <code>fetch</code> do with the URL? Basically, <code>fetch</code> returns a promise. You know that to get the output from a promise, you use <code>then</code>. So you write:</p>
<pre><code class="lang-javascript">.then(<span class="hljs-function">(<span class="hljs-params">res</span>)=&gt;</span>{})
</code></pre>
<p>After the response comes back, you use a callback function. Here, you log the response to the console:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(res);
</code></pre>
<p>This is how your <code>apiFunction</code> is set up.</p>
<p>Now call the function. You need to pass a URL for the API call. A popular choice is <a target="_blank" href="https://jsonplaceholder.typicode.com/">jsonplaceholder</a>, so use its <code>/todos/1</code> endpoint:</p>
<pre><code class="lang-javascript">apiFunction(<span class="hljs-string">"https://jsonplaceholder.typicode.com/todos/1"</span>);
</code></pre>
<p>Check the output. Notice that it appears after a short delay-this is asynchronous.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464859727/39dd7757-f04e-49f2-ac8a-46f2472a429e.png" alt="API Function Output" width="2560" height="1440" loading="lazy"></p>
<p>To make this clearer, write another line below:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"I am here"</span>);
</code></pre>
<p>Now the question is: which prints first? Without a doubt, "I am here" prints first, and then the output from <code>apiFunction</code> appears. This clearly demonstrates the flow of asynchronous operations. Since the response comes quickly, it might not have been obvious without this extra line.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464881162/59208d49-83f9-48af-8ab4-c9d1c453356b.png" alt="API Function with Log Output" width="2560" height="1440" loading="lazy"></p>
<p>What does this mean? The output is coming, right? Here, the connection to closures is that you passed the <code>url</code> parameter from outside when calling <code>apiFunction</code>. This <code>url</code> now exists inside the body of <code>apiFunction</code>. <code>fetch</code> takes it as a parameter, and then the callback function inside <code>then</code> executes much later.</p>
<p>By that time, the call to <code>apiFunction</code> has already finished, but the callback still remembers the variables from its scope. That's why even after the result arrives, you can still access <code>url</code>. To see this, print it:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(url);
</code></pre>
<p>Notice that the output is correct. This means that if there were more nested functions inside <code>then</code>, like another <code>then</code> inside a <code>then</code>, all the way down, the innermost function could still access the original <code>url</code>. And this is possible only because of closures.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464901905/8980f4a3-3eb9-4af1-868f-d3ef6d907e9b.png" alt="API Function URL Output" width="2560" height="1440" loading="lazy"></p>
<h3 id="heading-refactoring-with-external-function">Refactoring with External Function</h3>
<p><strong>Full code:</strong> <code>example-6.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-6.js</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">apiFunction</span>(<span class="hljs-params">url</span>) </span>{
    handleResponse = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">res</span>) </span>{
        <span class="hljs-built_in">console</span>.log(res);
        <span class="hljs-built_in">console</span>.log(url);
    };

    fetch(url).then(handleResponse);
    <span class="hljs-built_in">console</span>.dir(handleResponse);
}

apiFunction(<span class="hljs-string">"https://jsonplaceholder.typicode.com/todos/1"</span>);
</code></pre>
<p>To demonstrate, let’s rewrite the callback function inside <code>apiFunction</code> a little differently:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleResponse</span>(<span class="hljs-params">res</span>) </span>{}
</code></pre>
<p>This function simply does <code>console.log(url)</code>. Now pass <code>handleResponse</code> into the <code>then</code>. Then write:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.dir(handleResponse);
</code></pre>
<p>In the output, you'll see that inside <code>handleResponse</code>, the closure contains <code>url</code>. This is because it was part of <code>apiFunction</code>'s scope, so it can access it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464922631/3a2edbeb-d3e9-470d-bea3-fdf46144165e.png" alt="API Function with External Handler Output" width="2560" height="1440" loading="lazy"></p>
<h2 id="heading-advanced-example-closures-in-loops">Advanced Example - Closures in Loops</h2>
<p>Finally, let’s look at another example that often comes up in job interviews. This one is a bit more complex and tricky, and it shows how using closures inside loops can create unpredictable output.</p>
<h3 id="heading-synchronous-loop-example">Synchronous Loop Example</h3>
<p><strong>Full code:</strong> <code>example-7.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-7.js</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">a</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(i);
    }
    a();
}
</code></pre>
<p>Let’s write a simple for loop:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {}
</code></pre>
<p>This loop will run three times, and inside it we’ll define another function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">a</span>(<span class="hljs-params"></span>) </span>{}
</code></pre>
<p>Inside this function, you simply do:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(i);
</code></pre>
<p>From this, you see that the function <code>a</code> exists within the scope of the <code>for loop</code>, but in reality, it's also accessible in the global scope. Then you call the function <code>a</code>:</p>
<pre><code class="lang-javascript">a();
</code></pre>
<p>The expected output would be 0, 1, 2. First, the value of <code>i</code> prints 0, then 1, then 2 – one after another. Looking at the output, you see 0, 1, 2. This is because you defined <code>i</code> using <code>let</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763464949327/23ded10a-19c2-4aff-9d11-927e179c2c82.png" alt="Synchronous Loop Output" width="2560" height="1440" loading="lazy"></p>
<p><strong>Full code:</strong> <code>example-7.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-7.js</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">a</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(i);
    }
    a();
}
</code></pre>
<p>If you remove <code>let</code> and use <code>var</code> instead, what happens? Even with <code>var</code>, the output will be the same in this simple case because <code>var</code> works outside the block scope. Writing <code>for (var i = 0)</code> or declaring <code>var i</code> separately behaves effectively the same.</p>
<pre><code class="lang-js"><span class="hljs-comment">// example-7.js</span>

<span class="hljs-keyword">var</span> i;
<span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">a</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(i);
    }
    a();
}
</code></pre>
<p>So in this case, there's no problem. A closure isn't required because you are running the function in the global scope. Your <code>i</code> prints 0, then 1, then 2, and everything works correctly.</p>
<h3 id="heading-asynchronous-loop-example">Asynchronous Loop Example</h3>
<p><strong>Full code:</strong> <code>example-7.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-7.js</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(i);
    }, <span class="hljs-number">1000</span> * i);
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After for loop"</span>);
</code></pre>
<p>Now let's go back and use <code>let</code> for <code>i</code> again. Suppose you want to call the <code>a</code> function from outside the loop. Imagine you wrap the function call in a <code>setTimeout</code>, and in the first parameter you pass the body of <code>a</code> as a callback, while the second parameter is <code>1000 * i</code> milliseconds.</p>
<p>Using this <code>1000 * i</code>, you want 0 to print after 1 second, 1 after 2 seconds, and 2 after 3 seconds. When you run this, the output comes exactly as expected: after 1 second, 0 prints; after 2 seconds, 1 prints; and after 3 seconds, 2 prints.</p>
<p>But here's the important point: the <code>for</code> loop itself is synchronous, while the functions inside <code>setTimeout</code> are asynchronous. That means the functions inside <code>setTimeout</code> will execute one by one according to the timer, only after the loop has finished. First after 1 second, then after 2, and then after 3.</p>
<p>You can verify this asynchronous behavior. Suppose at the end of the loop you write:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After for loop"</span>);
</code></pre>
<p>Now, if you check the output, "After for loop" prints first, then after 1 second, 0 prints, after 2 seconds, 1 prints, and finally 2 prints. This clearly shows how asynchronous functions execute, right? No confusion there.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465056351/9ca676db-c54a-4dc2-9ac8-0bbf1cf08be4.gif" alt="Asynchronous Loop Output" width="1138" height="640" loading="lazy"></p>
<h3 id="heading-the-var-vs-let-problem">The <code>var</code> vs <code>let</code> Problem</h3>
<p><strong>Full code:</strong> <code>example-7.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-7.js</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(i);
    }, <span class="hljs-number">1000</span> * i);
}
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After for loop"</span>);
</code></pre>
<p>Now, let's see what happens if you replace <code>let i</code> with <code>var i</code>. The interesting part is, if you use "var i" instead of "let i", the behavior changes. All three outputs end up being 3. You don't get 0, 1, 2 like before. That's exactly the tricky part of this question.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465090022/87518cc5-4942-4c2e-a728-a11751d9a552.png" alt="Var Loop Problem Output" width="2560" height="1440" loading="lazy"></p>
<p>This question often comes up in job interviews because it's a bit advanced, but if you understand closures and the difference between <code>let</code> and <code>var</code> scopes, it's not complicated at all. You can analyze this by going back to <code>let</code>. Remove <code>var</code> and write:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>;
</code></pre>
<p>Now the expected output is 0, 1, 2. <code>let</code> is block-scoped, meaning this <code>i</code> exists only inside the loop and has no effect outside.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465164777/ba0b0084-95db-4de5-a1e6-67aaa8172c51.gif" alt="Let Loop Output" width="1138" height="640" loading="lazy"></p>
<p>During the first iteration, <code>i</code> is 0, and the <code>setTimeout</code> function is defined. This function will be called after the loop finishes, so a closure is used to remember the value of i. The callback needs a closure to reference i correctly. Since <code>let</code> doesn't leak outside the loop, each iteration creates a new i. For example, when i becomes 1, it's a completely separate <code>i</code> from the previous iteration.</p>
<p><strong>Full code:</strong> <code>example-7.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-7.js</span>

<span class="hljs-keyword">var</span> i;

<span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(i);
    }, <span class="hljs-number">1000</span> * i);
}
<span class="hljs-built_in">console</span>.log(i);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After for loop"</span>);
</code></pre>
<p>So, when this function runs the second time, it references this new i. But with <code>var</code>, the situation is different. <code>var</code> is function-scoped, so the same variable exists outside the loop. If you write:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> i;
</code></pre>
<p>and then use the loop:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {}
</code></pre>
<p>there is only one i. Changing i inside the loop modifies the same i – no new i is created. So when the setTimeout callbacks execute, they all reference that same i. From previous examples, you know setTimeout callbacks run after the loop finishes. Now, after the loop ends, what's the value of i? Since you used <code>var</code>, i has become 3.</p>
<p>Check it with:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(i);
</code></pre>
<p>In the console, you'll see 3 prints first. That means that when the callbacks execute, they all reference the same i, which is already 3.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465201159/7730557a-5255-4c32-8f46-ca01c11a6899.png" alt="Var Loop Problem with Log Output" width="2560" height="1440" loading="lazy"></p>
<p>So every console.log in the callbacks prints i = 3, which explains the output perfectly.</p>
<h3 id="heading-using-consoledir-with-loop-closures">Using <code>console.dir</code> with Loop Closures</h3>
<p><strong>Full code:</strong> <code>example-7.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-7.js</span>

<span class="hljs-comment">// var i;</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myFunc</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(i);
    }

    <span class="hljs-built_in">setTimeout</span>(myFunc, <span class="hljs-number">1000</span> * i);

    <span class="hljs-built_in">console</span>.dir(myFunc);
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After for loop"</span>);
</code></pre>
<p>To understand this even better, you can use "console.dir" like before.</p>
<p>Let's see how. First, you'll stick with the <code>let</code> case. So in the for loop you write:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>;
</code></pre>
<p>You comment out the global "var i;" since <code>let</code> is block-scoped. Now let's see how the closure works. The closure is created inside the setTimeout callback function, and you want to inspect this callback function.</p>
<p>For that, you define:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myFunc</span>(<span class="hljs-params"></span>) </span>{}
</code></pre>
<p>and pass this myFunc inside setTimeout. Then, to inspect it, write:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.dir(myFunc);
</code></pre>
<p>If you run this, the browser shows the same output. That means the dir of myFunc appears three times, but in Chrome's console, it only prints once. Chrome wraps similar objects together, so even though the internal properties are different, it doesn't display them separately. To see each property individually, take the next step.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465312812/f4ec260c-2b8f-474f-a1ad-59797eda63d4.gif" alt="Let Loop with Dir Output" width="1138" height="640" loading="lazy"></p>
<p>Below the dir, write:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"---"</span>);
</code></pre>
<p>This acts as a separator. Now, when the browser prints myFunc's dir, it also prints the separator, making it clear that each instance is separate.</p>
<p>At the same time, outside the for loop, add:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After for loop"</span>);
</code></pre>
<p>Now, if you check the output, the browser prints 'After for loop' first, then 0, 1, 2. When you defined it, the console logs show myFunc and the dashes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465334580/a92fd163-4095-4b6a-bdb5-f239350a7416.png" alt="Let Loop with Dir and Separator Output" width="2560" height="1440" loading="lazy"></p>
<p>Notice, when i is 0, the closure holds i = 0. When i = 1, the closure holds i = 1. When i = 2, the closure holds i = 2. So, all three values exist as references until the end, which is why you get three separate outputs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465373352/5e8903fa-76c4-4031-9a09-d45e9cd29e5f.gif" alt="Let Loop Closure Values Output" width="1138" height="640" loading="lazy"></p>
<h3 id="heading-the-var-loop-problem">The <code>var</code> Loop Problem</h3>
<p><strong>Full code:</strong> <code>example-7.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-7.js</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myFunc</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">console</span>.log(i);
    }

    <span class="hljs-built_in">setTimeout</span>(myFunc, <span class="hljs-number">1000</span> * i);

    <span class="hljs-built_in">console</span>.dir(myFunc);

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"---"</span>);
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After for loop"</span>);

<span class="hljs-built_in">console</span>.log(i);
</code></pre>
<p>But what happens if you replace <code>"let i"</code> with <code>"var i"</code>? After printing <code>'After for loop'</code>, all three outputs show 3. How? When i is 0, there's no closure because var moves this variable to the global scope. Unlike the previous example, no closure is needed here. Var exists in the global scope, and i changes within that same global variable.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465417027/24635534-867e-4b9d-a4cf-637abbd4610c.png" alt="Var Loop with Dir Output" width="2560" height="1440" loading="lazy"></p>
<p>So, if you expand the first myFunc in the console and look for i in the global scope, you'll see i = 3. Why? Because the for loop finishes first, and at the end, i becomes 3. At the moment of <code>'After for loop'</code>, i is 3. If you do "console.log(i)" there, the browser prints 3. This means, when the reference values are called, they still use the reference to that i. Even if i changes later in the program, since the calls happen afterward, the reference values get the updated i.</p>
<p>That's why the first call shows 3, the second call shows 3, and the third call also shows 3. If you expand them all, you'll see i = 3 everywhere. This happens because no closure is used here; it's referencing the original i in the global scope, which keeps updating.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465457673/56530a97-5bd4-4f67-9311-77655b9638cb.gif" alt="Var Loop Closure Values Output" width="1138" height="640" loading="lazy"></p>
<p>The difference in scope between let and var is why the output changes completely.</p>
<h3 id="heading-fixing-the-var-loop-problem-with-iife">Fixing the <code>var</code> Loop Problem with IIFE</h3>
<p>To fix this var issue, you can create an IIFE inside the for loop. This IIFE will take one parameter: in this case, the value of your loop variable "i."</p>
<p><strong>Full code:</strong> <code>example-7.js</code></p>
<pre><code class="lang-js"><span class="hljs-comment">// example-7.js</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
    (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">i</span>) </span>{
        <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myFunc</span>(<span class="hljs-params"></span>) </span>{
            <span class="hljs-built_in">console</span>.log(i);
        }

        <span class="hljs-built_in">setTimeout</span>(myFunc, <span class="hljs-number">1000</span> * i);

        <span class="hljs-built_in">console</span>.dir(myFunc);

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"---"</span>);
    })(i);
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After for loop"</span>);
</code></pre>
<p>You write the code. Inside the IIFE, you're passing a parameter named "i." Of course, you can name it anything you want – you already know that. But for now, just keep it as "i." Then, when you call the IIFE, pass the loop's "i" value into it. Nice, right?</p>
<p>Let's see what the output looks like. This time, you get 0, 1, and 2 correctly. So, why is it fixed now? Because "i" is now inside its own scope within the IIFE. Whenever you pass "i" to myFunc, a separate copy of that "i" is created as a parameter inside myFunc, and that copy is what gets used inside the function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465482476/0939504b-40c4-4b9c-b698-a55f266f24c4.gif" alt="IIFE Loop with Dir Output" width="1138" height="640" loading="lazy"></p>
<p>Everything's clear now, right? If you expand the dirs at the end, you'll see: the last one has "i = 2" in its closure, the second one has "i = 1," and the first one has "i = 0." Perfectly clear, isn't it?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763465516842/0c708a0d-f0c6-44de-828e-61827375ecc1.gif" alt="IIFE Loop Closure Values Output" width="1138" height="640" loading="lazy"></p>
<h2 id="heading-summary-and-key-takeaways">Summary and Key Takeaways</h2>
<p>If you have a solid grasp of the overall concepts discussed here, and if you practice all these examples repeatedly, your understanding of closures will become much stronger.</p>
<p>Of course, there are more complex examples of closures, but the basics we've covered today are the most important. Once you understand them step by step, you'll be able to create many use cases yourself and debugging will no longer be difficult. Because now, with just a glance at <code>console.dir()</code> or by playing with the code a bit, you can see how closures actually work.</p>
<p>Not having a good understanding of closures can make you get stuck in many parts of JavaScript, especially when working with asynchronous code.</p>
<h3 id="heading-to-summarize">To summarize:</h3>
<p>If you're asked in a job interview, "What is a Closure?" you can answer simply:</p>
<blockquote>
<p>A closure is a mechanism where a function remembers variables outside its own scope and can access them whenever needed.</p>
</blockquote>
<p>In other words, values that aren't inside the function itself, but the function takes a reference from its parent or outer scope. This is what we call a Closure.</p>
<p><strong>Closure = Function + Remembered Values</strong></p>
<p>This is why closures are so important in job interviews. They show how deeply a programmer understands JavaScript. A programmer who understands closures can clearly grasp JavaScript's internal behavior, memory handling, and asynchronous flow.</p>
<h3 id="heading-the-importance-of-closures">The Importance of Closures</h3>
<p>JavaScript was originally created just for small interactive tasks in the browser, but now you can build large-scale applications, even backend systems, with it. The reason behind this is powerful concepts in JavaScript like Closures, Prototypes, and more.</p>
<p>Many people say, "I know var, let, const, so tell me about closures." But as you've seen, var, let, and const aren't that simple either. This is where the understanding of closures begins.</p>
<h2 id="heading-final-words">Final Words</h2>
<p>We covered a lot in this handbook! If reading this all at once feels overwhelming, you can break it into parts and read it step by step. I’ve tried to explain the whole topic very simply, piece by piece. If there are any areas that could be clearer, I appreciate your feedback. But once you’ve really understood and digested this info, you shouldn’t be intimidated by the word "Closure" ever again.</p>
<p>You can find all the source code from this tutorial in this <a target="_blank" href="https://github.com/logicbaselabs/understanding-closure/">GitHub repository</a>. If it helped you in any way, consider giving it a star to show your support!</p>
<p>If you found the information here valuable, feel free to share it with others who might benefit from it. I’d really appreciate your thoughts – mention me on X <a target="_blank" href="https://x.com/sumit_analyzen">@sumit_analyzen</a> or on Facebook <a target="_blank" href="https://www.facebook.com/sumit.analyzen">@sumit.analyzen</a>, <a target="_blank" href="https://www.youtube.com/@logicBaseLabs">watch</a> my coding tutorials, or simply <a target="_blank" href="https://www.linkedin.com/in/sumitanalyzen/">connect with me</a> on LinkedIn. You can also checkout my official website <a target="_blank" href="https://www.sumitsaha.me">sumitsaha.me</a> for more details about me.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
