<story><title>JavaScript garbage collection and closures</title><url>https://jakearchibald.com/2024/garbage-collection-and-closures/</url></story><parent_chain><item><author>DanielHB</author><text>This behavior is required because eval exists:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  function test(text) {
    const a = 1
    function inner() {
      console.log(eval(text))
    }
    inner()
  }
  test(&amp;quot;() =&amp;gt; { return a }&amp;quot;)
 &lt;/code&gt;&lt;/pre&gt;
prints 1 to the console&lt;p&gt;This happens because the closure&amp;#x27;s context object is shared between all closures in a given scope. So as soon as one variable from a give scope is accessed through a closure then all variables will be retained by all inner functions.&lt;p&gt;Technically the engines could be optimizing it when no eval used is detected or when in strict mode (which blocks eval), but I guess that dynamically dropping values from a closure context based on inner lexical scopes can be really tricky thing to do and probably not worth the overhead.</text></item></parent_chain><comment><author>paulddraper</author><text>No. JS engines detect of eval in the AST.&lt;p&gt;It&amp;#x27;s why you can&amp;#x27;t rename eval and reference the current scope.&lt;p&gt;&lt;pre&gt;&lt;code&gt;  const eval2 = eval;
  (() =&amp;gt; {
    const a = 1;
    eval2(&amp;quot;a&amp;quot;);
  })();
  &amp;#x2F;&amp;#x2F; ReferenceError: a is not defined
&lt;/code&gt;&lt;/pre&gt;
---&lt;p&gt;The reason JS engines choose to share the closure record among all closures create in the function scope is purely for performance.&lt;p&gt;&lt;pre&gt;&lt;code&gt;  function f() {
    const a = {};
    const b = {};
    return [
      () =&amp;gt; a,
      () =&amp;gt; b,
    ];
  }
&lt;/code&gt;&lt;/pre&gt;
Both functions share the same single closure record, referencing a and b.&lt;p&gt;JavaScript developers have rediscovered this over and over and over again.&lt;p&gt;* Meteor.js (2013) [1]&lt;p&gt;* My personal journey (2013) [2]&lt;p&gt;[1] &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;blog.meteor.com&amp;#x2F;an-interesting-kind-of-javascript-memory-leak-8b47d2e7f156&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;blog.meteor.com&amp;#x2F;an-interesting-kind-of-javascript-me...&lt;/a&gt;&lt;p&gt;[2] &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;stackoverflow.com&amp;#x2F;questions&amp;#x2F;19798803&amp;#x2F;how-javascript-closures-are-garbage-collected&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;stackoverflow.com&amp;#x2F;questions&amp;#x2F;19798803&amp;#x2F;how-javascript-...&lt;/a&gt;</text></comment>
<story><title>JavaScript garbage collection and closures</title><url>https://jakearchibald.com/2024/garbage-collection-and-closures/</url></story><parent_chain><item><author>DanielHB</author><text>This behavior is required because eval exists:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  function test(text) {
    const a = 1
    function inner() {
      console.log(eval(text))
    }
    inner()
  }
  test(&amp;quot;() =&amp;gt; { return a }&amp;quot;)
 &lt;/code&gt;&lt;/pre&gt;
prints 1 to the console&lt;p&gt;This happens because the closure&amp;#x27;s context object is shared between all closures in a given scope. So as soon as one variable from a give scope is accessed through a closure then all variables will be retained by all inner functions.&lt;p&gt;Technically the engines could be optimizing it when no eval used is detected or when in strict mode (which blocks eval), but I guess that dynamically dropping values from a closure context based on inner lexical scopes can be really tricky thing to do and probably not worth the overhead.</text></item></parent_chain><comment><author>jaffathecake</author><text>Nah, that&amp;#x27;s not it. Browsers do statically detect if eval is there or not, and react accordingly. This is possible because of &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;developer.mozilla.org&amp;#x2F;en-US&amp;#x2F;docs&amp;#x2F;Web&amp;#x2F;JavaScript&amp;#x2F;Reference&amp;#x2F;Global_Objects&amp;#x2F;eval#direct_and_indirect_eval&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;developer.mozilla.org&amp;#x2F;en-US&amp;#x2F;docs&amp;#x2F;Web&amp;#x2F;JavaScript&amp;#x2F;Refe...&lt;/a&gt;</text></comment>