<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged heapmemory</title>
<link>https://coderlegion.com/tag/heapmemory</link>
<description>Powered by Question2Answer</description>
<item>
<title># Understanding JavaScript Closures Through Call Stack, Heap Memory &amp; `[[Scopes]]`</title>
<link>https://coderlegion.com/22068/understanding-javascript-closures-through-call-stack-heap-memory-scopes</link>
<description>&lt;blockquote&gt;&lt;p&gt;Closures aren't magic—they're simply JavaScript's way of keeping data alive when a function still needs it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Every JavaScript developer has heard statements like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;A closure is a function that remembers variables from its outer scope.&quot;&lt;/li&gt;
&lt;li&gt;&quot;The inner function closes over variables.&quot;&lt;/li&gt;
&lt;li&gt;&quot;Closures preserve the lexical environment.&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;How does a function actually remember variables?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Where are those variables stored after the outer function finishes?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why doesn't JavaScript delete them?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let's go beyond the textbook definition and see what actually happens inside the JavaScript engine.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-two-main-players-inside-the-javascript-engine&quot;&gt;The Two Main Players Inside the JavaScript Engine&lt;/h2&gt;
&lt;p&gt;Whenever a function executes, two important memory areas are involved:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Call Stack&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heap Memory&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Understanding closures is really about understanding &lt;strong&gt;where JavaScript stores variables&lt;/strong&gt; and &lt;strong&gt;why some of them survive after a function finishes executing.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;1-what-happens-in-a-normal-function-&quot;&gt;1. What Happens in a Normal Function?&lt;/h2&gt;
&lt;p&gt;Consider a simple function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function greet() {
    let name = &quot;JavaScript&quot;;
    console.log(name);
}

greet();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When &lt;code&gt;greet()&lt;/code&gt; executes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An &lt;strong&gt;Execution Context&lt;/strong&gt; is created.&lt;/li&gt;
&lt;li&gt;Local variables (&lt;code&gt;name&lt;/code&gt;) belong to that execution.&lt;/li&gt;
&lt;li&gt;The execution context is pushed onto the &lt;strong&gt;Call Stack&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;Call Stack

┌─────────────────────────┐
│ Execution Context       │
│ name = &quot;JavaScript&quot;     │
└─────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After the function finishes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The execution context is popped off the stack.&lt;/li&gt;
&lt;li&gt;No code references &lt;code&gt;name&lt;/code&gt; anymore.&lt;/li&gt;
&lt;li&gt;It becomes eligible for &lt;strong&gt;Garbage Collection&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything is cleaned up.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;2-what-changes-when-a-closure-is-created-&quot;&gt;2. What Changes When a Closure Is Created?&lt;/h2&gt;
&lt;p&gt;Now look at this example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function outerFunction() {

    let count = 0;

    function innerFunction() {
        count++;
        console.log(count);
    }

    return innerFunction;
}

const counter = outerFunction();

counter();
counter();
counter();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;1
2
3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But wait...&lt;/p&gt;
&lt;p&gt;&lt;code&gt;outerFunction()&lt;/code&gt; already finished executing.&lt;/p&gt;
&lt;p&gt;Its execution context has been removed from the Call Stack.&lt;/p&gt;
&lt;p&gt;So why is &lt;code&gt;count&lt;/code&gt; still available?&lt;/p&gt;
&lt;p&gt;That's where &lt;strong&gt;closures&lt;/strong&gt; come in.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;behind-the-scenes&quot;&gt;Behind the Scenes&lt;/h2&gt;
&lt;p&gt;When JavaScript notices that &lt;code&gt;innerFunction&lt;/code&gt; uses &lt;code&gt;count&lt;/code&gt;, it understands:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;This variable will still be needed after &lt;code&gt;outerFunction()&lt;/code&gt; returns.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Instead of letting &lt;code&gt;count&lt;/code&gt; disappear with the execution context, the engine keeps it alive.&lt;/p&gt;
&lt;p&gt;Three important things happen behind the scenes.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;step-a-captured-variables-are-kept-in-heap-memory&quot;&gt;Step A — Captured Variables Are Kept in Heap Memory&lt;/h2&gt;
&lt;p&gt;The variables that are captured by an inner function are stored inside an internal object called the &lt;strong&gt;Lexical Environment&lt;/strong&gt; (often called the Closure Context).&lt;/p&gt;
&lt;p&gt;Conceptually, you can think of it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;Heap Memory

Lexical Environment

{
    count: 0
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unlike the Call Stack, heap memory isn't destroyed when the function returns.&lt;/p&gt;
&lt;p&gt;This allows the captured variables to stay alive.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Engines don't literally &quot;move&quot; variables from the stack to the heap. Instead, captured variables are stored in a heap-allocated lexical environment so they can outlive the function call.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&quot;step-b-the-secret-link-scopes-&quot;&gt;Step B — The Secret Link (&lt;code&gt;[[Scopes]]&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;Every function internally carries a hidden reference called:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;[[Scopes]]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This hidden reference points to the lexical environment containing the variables it needs.&lt;/p&gt;
&lt;p&gt;Conceptually:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;counter
   │
   ▼
[[Scopes]]
   │
   ▼
Lexical Environment
{
   count: 0
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even after &lt;code&gt;outerFunction()&lt;/code&gt; has finished, the returned function still knows exactly where &lt;code&gt;count&lt;/code&gt; lives.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;step-c-the-scope-chain&quot;&gt;Step C — The Scope Chain&lt;/h2&gt;
&lt;p&gt;Later, when you execute:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;counter();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;JavaScript performs variable lookup in this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check the function's local scope.&lt;/li&gt;
&lt;li&gt;If not found, follow &lt;code&gt;[[Scopes]]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Search the lexical environment.&lt;/li&gt;
&lt;li&gt;Continue upward until the variable is found.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This lookup process is called the &lt;strong&gt;Scope Chain&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;visualizing-the-entire-process&quot;&gt;Visualizing the Entire Process&lt;/h2&gt;
&lt;h4 id=&quot;before-outerfunction-returns&quot;&gt;Before &lt;code&gt;outerFunction()&lt;/code&gt; Returns&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;Call Stack

┌────────────────────────────┐
│ outerFunction()            │
│ count = 0                  │
│ innerFunction()            │
└────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h4 id=&quot;after-returning&quot;&gt;After Returning&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;Call Stack

┌──────────────────────┐
│ Global Execution     │
└──────────────────────┘


Heap Memory

┌────────────────────────┐
│ Lexical Environment    │
│ count = 0              │
└────────────────────────┘

        ▲
        │
     [[Scopes]]
        │
        ▼

innerFunction
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The execution context is gone.&lt;/p&gt;
&lt;p&gt;The variable survives because the returned function still references it.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;a-simple-analogy&quot;&gt;A Simple Analogy&lt;/h2&gt;
&lt;p&gt;Imagine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;outerFunction()&lt;/code&gt; is a hotel room.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count&lt;/code&gt; is an important document.&lt;/li&gt;
&lt;li&gt;Before checking out, you place the document in a secure locker (Heap Memory).&lt;/li&gt;
&lt;li&gt;You hand the locker key (&lt;code&gt;[[Scopes]]&lt;/code&gt;) to your child (&lt;code&gt;innerFunction&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even after the hotel room is empty, your child still has the key and can access the document whenever needed.&lt;/p&gt;
&lt;p&gt;That's exactly how closures work.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;why-are-closures-useful-&quot;&gt;Why Are Closures Useful?&lt;/h2&gt;
&lt;h3 id=&quot;1-data-privacy&quot;&gt;1. Data Privacy&lt;/h3&gt;
&lt;p&gt;Closures let you create private variables.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function createCounter() {

    let count = 0;

    return {
        increment() {
            count++;
        },

        getCount() {
            return count;
        }
    };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nobody outside can directly modify &lt;code&gt;count&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-maintaining-state&quot;&gt;2. Maintaining State&lt;/h3&gt;
&lt;p&gt;Closures allow functions to remember information between calls.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const counter = outerFunction();

counter();
counter();
counter();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The value of &lt;code&gt;count&lt;/code&gt; persists without using global variables.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;key-takeaways&quot;&gt;Key Takeaways&lt;/h2&gt;
&lt;p&gt;✔ A closure is created when an inner function uses variables from its outer scope.&lt;/p&gt;
&lt;p&gt;✔ JavaScript keeps those captured variables alive inside a heap-allocated lexical environment.&lt;/p&gt;
&lt;p&gt;✔ The returned function stores a hidden reference called &lt;code&gt;[[Scopes]]&lt;/code&gt; to that environment.&lt;/p&gt;
&lt;p&gt;✔ As long as the function exists, the captured variables cannot be garbage collected.&lt;/p&gt;
&lt;p&gt;✔ Variable lookup through these linked environments is called the &lt;strong&gt;Scope Chain&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;final-thought&quot;&gt;Final Thought&lt;/h3&gt;
&lt;p&gt;Closures aren't magic.&lt;/p&gt;
&lt;p&gt;They're simply the JavaScript engine preserving the variables that are still needed.&lt;/p&gt;
&lt;p&gt;Once you understand the relationship between the &lt;strong&gt;Call Stack&lt;/strong&gt;, &lt;strong&gt;Heap Memory&lt;/strong&gt;, &lt;strong&gt;Lexical Environment&lt;/strong&gt;, and the hidden &lt;strong&gt;&lt;code&gt;[[Scopes]]&lt;/code&gt;&lt;/strong&gt; reference, closures become one of the most elegant and powerful features of JavaScript.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22068/understanding-javascript-closures-through-call-stack-heap-memory-scopes</guid>
<pubDate>Tue, 07 Jul 2026 17:34:11 +0000</pubDate>
</item>
</channel>
</rss>