Search code examples
javascriptfirefoxbrowsergarbage-collection

Will element not in DOM but with attached handlers be removerd from browser memory using GC?


In order to get image dimensions in my js-script, I create temporary <img> element without attaching it to DOM. This is the simplified version of a function I wrote:

function testImage(i) {
    let tester = document.createElement('img');
    tester.onload = function() { console.log(tester.naturalWidth); }
    tester.src = `${i}.jpg`;
}
  1. tester is used only inside function.
  2. tester is never arrached to DOM.
  3. onload function has some actions to do with this tester. I wonder if it will interfere with garbage collector.

Let's assume this can be called many many many times. Will those testers consume memory? Or will garbage collector remove them?

PS: Console for (let k=0; k < 1000000000; k++) { testImage(k) } eats my whole memory.

PS2: I know I can write script that will reuse same <img> element or elements. But I am curious about first approach.

UPD: As @rojo said GC cleans memory, but I did not notice it in my case because:

  1. Looks like GC does not clean memory in synchronous loop (at least in browser). The line for (let k=0; k < (1000*1000); k++) { testImage(k) } eats a lot of memory, but 1000 repeats of loops with 1000 test executed with setTimeout does not consume so much memory. Manual execution of different sized loops shows that memory released after loop is finished.

  2. This particular script writes many logs to browser console. If console is open, it consumes more memory to keep logs. When I rewrote tester to prevent logging, memory consumption with opened console decreased, but GC worked the same way.


Solution

  • Based on MDN (scroll down to Limitation: Circular References), those variables will be deleted.

    All variables created inside of a function will be deleted once the function finishes, with no exceptions.

    function foo() {
      var a = "data";
      console.log(a); // "data"
    } // variable is deleted
    console.log(a); // Uncaught ReferenceError: a is not defined