Dinesh Patra
Dinesh Patra

Reputation: 1135

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.

Please help me in javascript dom manipulation.

Upvotes: 3

Views: 2013

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075337

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>'
);

Upvotes: 7

Related Questions