I know this kind of stuff can cause memory leak because the child element has a reference in global scope :
let parent = document.getElementById("parent");
let child = document.getElementById("child");
parent.addEventListener("click", function(){
child.remove();
});
To avoid this, child should be in local scope (in a function). But if I do :
class foo() {
parent = document.getElementById("parent");
child = document.getElementById("child");
remove() {
var that = this;
this.parent.addEventListener("click", function(){
that.child.remove();
});
}
let Foo = new foo;
Foo.remove();
Will I run in the same problem or not? It is unclear. For me, It should not because class has it's own scope but I would like a confirmation please!
To avoid this, child should be in local scope (in a function)
That's not quite enough.
(function() {
let parent = document.getElementById("parent");
let child = document.getElementById("child");
parent.addEventListener("click", function(){
child.remove();
});
}());
will still leak the memory since the document holds onto the #parent
element which holds onto the click event listener which is a closure over the child
variable which holds onto the #child
element. To fix this, you'll need to write
(function() {
let parent = document.getElementById("parent");
parent.addEventListener("click", function(){
let child = document.getElementById("child");
if (child) child.remove();
});
}());
or
(function() {
let parent = document.getElementById("parent");
let child = document.getElementById("child");
parent.addEventListener("click", function(){
child.remove();
}, {once: true}); // automatically removeAddEventListener after first event
}());
But if I do [use a
class
] will I run in the same problem or not? It should not because class has its own scope.
Yes, same problem as with the global variable even. The Foo
variable to store your instance is global, and Foo.child
is still a globally accessible reference. But even you didn't store the instance in a global variable, you'd still leak the reference to the #child
element through the event listener on the #parent
element, just like in my first snippet.
And no, class
es don't have their own scope. Methods do have, but the properties (class fields in your example) are not "scoped" at all, they're just properties of objects. Their references can be followed much easier than that of variables in closures. You don't even need the class
to analyse this, your code is exactly equivalent to
let Foo = {
parent: document.getElementById("parent"),
child: document.getElementById("child"),
};
(function remove() {
var that = Foo;
Foo.parent.addEventListener("click", function(){
that.child.remove();
});
}());