Reputation: 163488
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.
Upvotes: 6
Views: 2262
Reputation:
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 exited 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() {
console.log(div);
};
}
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.
Upvotes: 7
Reputation: 1
You can utilize Take Heap Shot
, Record Allocation Time
, Record Allocation Profile
at Profiles
tab at DevTools
to determine the memory status of a variable.
See
Uncover DOM leaks
The heap profiler has the ability to reflect bidirectional dependencies between browser native objects (DOM nodes, CSS rules) and JavaScript objects. This helps to discover otherwise invisible leaks happening due to forgotten detached DOM subtrees floating around.
DOM leaks can be bigger than you think. Consider the following sample - when is the #tree GC?
var select = document.querySelector; var treeRef = select("#tree"); var leafRef = select("#leaf"); var body = select("body"); body.removeChild(treeRef); //#tree can't be GC yet due to treeRef treeRef = null; //#tree can't be GC yet due to indirect //reference from leafRef leafRef = null; //#NOW can be #tree GC
#leaf
maintains a reference to it's parent (parentNode) and recursively up to#tree
, so only when leafRef is nullified is the WHOLE tree under#tree
a candidate for GC.
If there are no other references to canvas
, it should be garbage collected. You can be certain of this by checking heap snapshot.
Upvotes: 3
Reputation: 38253
First of all, there is a large caveat that not every implementation uses the same garbage collection algorithm because it hasn't been standardized. Namely, older versions of IE.
Quoting the MDN documentation:
Internet Explorer 6 and 7 are known to have reference-counting garbage collectors for DOM objects
However, most modern browsers use mark-and-sweep garbage collection:
As of 2012, all modern browsers ship a mark-and-sweep garbage-collector. All improvements made in the field of JavaScript garbage collection (generational/incremental/concurrent/parallel garbage collection) over the last few years are implementation improvements of this algorithm, but not improvements over the garbage collection algorithm itself nor its reduction of the definition of when "an object is not needed anymore".
Mark-and-Sweep will remove an object when it is unreachable. So, in your case, if you assign a new value to the canvas
variable, your newly created element will be unreachable and be marked for garbage collection. It may take up memory for a brief period of time, until the garbage collector runs. Also, because you used let
it may be garbage collected as soon as the block scope it's located in is no longer needed in memory.
Upvotes: 2
Reputation: 41893
Okey, I can give you a worthy answer right now, because I've checked it out by myself. In your case, you have just made a new variable and set its value to document.createElement('canvas')
.
Until you decide to append that variable into your DOM, it's nothing more than just a value stored inside a variable. And with setting the value to null, the variable is now being stored and takes memory as a normal, single, empty variable.
The situation would be quite contrary, if you would append it into your document. The element wouldn't just be deleted with setting the variable's value to null and then it would waste memory.
Upvotes: 1