Looking to understand memory leaks in Javascript at the circular reference of DOM and JS objects thought that the following isOnloadCalled()
would not yield "yes", but it does. why?
function isOnloadCalled() {
var img = new Image();
img.onload = function () {
console.log("yes");
};
img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAxJREFUCNdj+P//PwAF/gL+3MxZ5wAAAABJRU5ErkJggg==";
}
isOnloadCalled();
// yields: "yes"
For my confusion is related to the idea that the DOM object img
was created within the function scope of isOnloadCalled()
and via closure is also within its img.onload
handler. I would expect that the img
gets garbage collected as soon as becomes unreachable and hence its onload
handler was never triggered.
Since the a test in Chrome and Firefox showed that the result is an unexpected "yes", and the object was not garbage collected I seek in this question an answer detailling why the DOM.object's handler was calledd when indeed the DOM already lost all its reachable references and should have been garbage collected, even more so as it was never attached to the documents DOM tree.
Since before any event handler can be envoked there is the Javascript "Run-to-completion" paradigm and hence amble time for the browser to check img
is not referenced anymore and can be deleted, by this making a call to the onload handler obsolete.
The only explenation I have kind of come up with, and which may serve as part of an answer would be that with the isOnloadCalled()
last line being img.src = "[url]"
the still existing img
is "kept reachable" via its reference by the events that reference it from within the javascript message queue. But I am unsure if this is the right explanation.