Brad Brad - 15 days ago 4
Javascript Question

Clean-up of elements that are no longer referenced, and were never added to the document

Suppose I create a new element:

let canvas = document.createElement('canvas');

Now, later on in the script, I remove any JS references to it.

canvas = null;

Does the canvas element itself still exist, taking memory? Or will it be garbage collected like any other unreferenced object? Note that I haven't actually added it to the document.


Does the <canvas> element itself still exist, taking memory? Or will it be garbage collected like any other unreferenced object?

Yes, it still exists for the time being. Yes, it will be garbage collected in due time.

Other posters seem to be slightly confused about the difference in GC behavior between the canvas variable and the <canvas> element. Variables are allocated on the stack, not the heap. They occupy some tiny amount of memory on the stack as long as they are in scope. They remain in scope by virtue of being in the call chain. The memory they use is released when the function is executed and stack frame popped.

Elements, like other objects, are allocated on the heap, and subject to garbage collection. They are GC'd when no longer referenced. The <canvas> element could be made to be no longer referenced either by setting any variable referring to it to null or something else, or the (only) variable referring to it going out of scope.

There is of course one other case relating to memory management of variables, which is closures. A variable which is closed over continues to occupy (a tiny amount of) memory as long as the enclosed function is "in scope", in other words, something references it. The value of such a variable--be it a DOM element or an JS object or anything else--will not and cannot be GC'd until the function in the closure goes out of scope. Little example:

function a() {
  const div = document.createElement('div');
  return function() {

function b() {
  const func = a();

When b is entered, storage is allocated on the stack for func. a is called, which creates the DOM element and returns the inner function. At this point, div remains allocated because it has been closed over and is referenced from within the inner function. The DOM element remains in the heap. Once b exits, the variable func is popped off the stack frame, meaning that nothing refers to the closure function any longer. That means that div is no longer in scope. That in turns means that the element is no longer referenced and will be GC'd (eventually).

Bottom line is that you don't need to worry about any of this. It just works, barring pathological cases or engine bugs.