Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript dom manipulation memory leak

Hi I have created a dom using raw javascript DOM:

Javascript code:

var parentElm = document.createElement("div");
var child1 = document.createElement("p");
var child2 = document.createElement("p");

parentElm.id = "parent";
child1.id = "child1";
child2.id = "child2";

child1.innerHTML = "Hello";
child2.innerHTML = "world"; // Is it a good way 

parentElm.appendChild(child1);
parentElm.appendChild(child2);
document.body.appendChild(parentElm);

The resulted HTML is:

<div id="parent">
    <p id="child1">Hello</p>
    <p id="child2">World</p>
</div>

Now when I want to remove the above section, I do as following.

document.body.removeChild(parentElm);

Here I am afraid of javascript memory leak.

  • If I am removing parent element from body, does it totally removed from memory. ?
  • If I am removing parent element from body, does it's child elements are also removed from memory by garbage collector automatically. Or I need to remove child elements manually ?
  • Is using innerHTML in the above code is a good way (child1.innerHTML = "Hello";)

Please help me in javascript dom manipulation.

like image 367
Dinesh Patra Avatar asked Jul 29 '26 10:07

Dinesh Patra


1 Answers

If I am removing parent element from body, does it totally removed from memory. ?

If your parentElm, child1, and child2 variables are no longer in scope or you've set them to another value, yes.

If I am removing parent element from body, does it's child elements are also removed from memory by garbage collector automatically. Or I need to remove child elements manually ?

If your child1 and child2 variables are no longer in scope or you've set them to another value, yes, removing the parent is all you need to do to remove the children and allow them to be cleanned up.

Is using innerHTML in the above code is a good way (child1.innerHTML = "Hello";)

It's fine, and common practice.

So there's no memory leak here, for instance:

function addParagraphs() {
    var parentElm = document.createElement("div");
    var child1 = document.createElement("p");
    var child2 = document.createElement("p");

    parentElm.id = "parent";
    child1.id = "child1";
    child2.id = "child2";

    child1.innerHTML = "Hello";
    child2.innerHTML = "world"; // Is it a good way 

    parentElm.appendChild(child1);
    parentElm.appendChild(child2);
    document.body.appendChild(parentElm);
}

function removeElement(element) {
    if (element.remove) {
        element.remove(); // newer DOM method, not on all browsers
    } else if (element.parentNode) {
        element.parentNode.removeChild(element);
    }
}

addParagraphs();
removeElement(document.getElementById("parent"));

...because the variables in addParagraphs can all be reclaimed.

However, if you create a closure over those variables and you keep it, that can keep the elements in memory longer than you expect:

function addParagraphs() {
    var parentElm = document.createElement("div");
    var child1 = document.createElement("p");
    var child2 = document.createElement("p");

    parentElm.id = "parent";
    child1.id = "child1";
    child2.id = "child2";

    child1.innerHTML = "Hello";
    child2.innerHTML = "world"; // Is it a good way 

    parentElm.appendChild(child1);
    parentElm.appendChild(child2);
    document.body.appendChild(parentElm);

    return function() {
        console.log("Hi there");
    };
}

function removeElement(element) {
    if (element.remove) {
        element.remove(); // newer DOM method, not on all browsers
    } else if (element.parentNode) {
        element.parentNode.removeChild(element);
    }
}

var f = addParagraphs();
removeElement(document.getElementById("parent"));

The function we return from addParagraphs and store in f is a closure over the context it was created in. In theory, even though the function doesn't use parentElm, child1, or child2, it has a reference to the context where it was created, and that context has a reference to those variables, keeping them in memory. (Modern JavaScript engines can optimize this a bit.) So in theory, as long as we have a reference to f, those DOM elements can still exist in memory, kept alive by the variables that are kept alive by the function. It's still not necessarily a leak, if you release f at some point, but it's useful to remember.


Of course, you can also create those elements with less code:

var parentElm = document.createElement('p');
parentElm.id = "parent";
parentElm.innerHTML =
    '<p id="child1">Hello</p>' +
    '<p id="child2">world</p>';
document.body.appendChild(parentElm);

Or on modern browsers:

document.body.insertAdjacentHTML(
    'beforeend',
    '<p id="parent">' +
        '<p id="child1">Hello</p>' +
        '<p id="child2">world</p>' +
    '</p>'
);
like image 108
T.J. Crowder Avatar answered Aug 01 '26 01:08

T.J. Crowder



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!