Let’s assume I have the following code:
(function () {
const largeObject = provideSomeLargeObject();
const largeStaticListOfElements = document.querySelectorAll('span');
const someElementThatWillBeRemoved = document.getElementById('i-will-be-removed');
const elms = document.getElementsByClassName('click-me');
for (let i = 0; i < elms.length; ++i) {
const anotherLargeObject = provideAnotherLargeObject();
elms[i].addEventListener('click', function (e) {
// callback just uses i, which contains a literal value
e.preventDefault();
console.log(i);
});
}
// largeObject, largeStaticListOfElements, someElementThatWillBeRemoved, and anotherLargeObject
// are no longer used in this code. Should they be set to null to allow GC them?
})();
The event listeners create function scopes, and after executing the above code, the event listeners still exist, thus the outer function scopes are preserved so that the event handlers can use the variables they contain.
However, the event handlers just use some literal value from the outer scopes, but in these scopes there are other variables, that are not used anymore.
- Would the event listeners prevent garbage collecting the objects referenced by these variables, so I have to manually assign null to the variables at the end of the code,
- or are JavaScript engines smart enough to detect that the event handler never uses the variables, so the referenced objects can be GC even if the variables reside in a still existing function scope?
2
Answers
It’s not so much the event listeners, but how you declare each and every identifier throughout.
So if you’re seriously concerned about the Garbage Collector doing its job (and you should be), you might want to refrain from declaring everything as constants, unnecessarily!
Examples of GOOD constant declarations…
Examples of BAD constant declarations…
You get the drift…
NB: The Garbage Collector CANNOT collect constant declarations for they are pushed to the top of the code section by the O/S, where their exact size is preserved in memory throughout the page running, given that they can never grow or shrink in size; for they can never change their value.
Note that variables come in 2 flavors – primitives and objects. Primitives exists in a scope, you can’t reference them outside its own and child scopes (they are copied by value).
So in your example you just don’t care since you use a primitive only. If you remove event listeners or remove the elements from DOM, the whole construct is garbage collected (if the elements aren’t referenced elsewhere).
If you use objects and reference them outside the scope, you are in trouble and use
reference = null
for all outside references so the construct is garbage collected.