【问题标题】:Javascript dom manipulation memory leakJavascript dom 操作内存泄漏
【发布时间】:2015-12-07 08:07:45
【问题描述】:

您好,我使用原始 javascript DOM 创建了一个 dom:

Javascript 代码:

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

生成的 HTML 是:

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

现在当我想删除上面的部分时,我执行以下操作。

document.body.removeChild(parentElm);

这里我怕javascript内存泄漏。

  • 如果我要从正文中删除父元素,它会完全删除吗 从记忆里。 ?
  • 如果我要从正文中删除父元素,是 垃圾收集器也会自动从内存中删除子元素。或者我需要删除 手动子元素?
  • 在上面的代码中使用innerHTML是个好办法(child1.innerHTML = "Hello";)

请帮助我进行 javascript dom 操作。

【问题讨论】:

    标签: javascript jquery html dom memory-leaks


    【解决方案1】:

    如果我从正文中删除父元素,它是否完全从内存中删除。 ?

    如果您的 parentElmchild1child2 变量不再在范围内,或者您已将它们设置为其他值,是的。

    如果我从正文中删除父元素,垃圾收集器是否也会自动从内存中删除它的子元素。还是我需要手动移除子元素?

    如果您的 child1child2 变量不再在范围内,或者您已将它们设置为另一个值,是的,您只需删除父级即可删除子级并允许清理它们.

    在上面的代码中使用innerHTML是个好办法(child1.innerHTML = "Hello";)

    这很好,而且很常见。

    所以这里没有内存泄漏,例如:

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

    ...因为addParagraphs中的变量都是可以回收的。

    但是,如果您为这些变量创建一个闭包并保留它,则可以使元素在内存中的保留时间比您预期的要长:

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

    我们从addParagraphs 返回并存储在f 中的函数是一个闭包,它覆盖了创建它的上下文。理论​​上,即使该函数不使用parentElmchild1child2,它具有对创建它的上下文的引用,并且该上下文具有对这些变量的引用,将它们保存在内存中。 (现代 JavaScript 引擎可以对此进行一些优化。)所以理论上,只要我们有对 f 的引用,那些 DOM 元素仍然可以存在于内存中,由函数保持活动状态的变量保持活动状态。如果您在某个时候释放f,它仍然不一定是泄漏,但记住这一点很有用。


    当然,您也可以用更少的代码创建这些元素:

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

    或者在现代浏览器上:

    document.body.insertAdjacentHTML(
        'beforeend',
        '<p id="parent">' +
            '<p id="child1">Hello</p>' +
            '<p id="child2">world</p>' +
        '</p>'
    );
    

    【讨论】:

    • 非常感谢。明白你的意思了。只是为了澄清,在删除删除任何节点时,我需要将其引用分配给其他一些值,比如 null ?还需要为其子元素做 smae 吗?
    • 谢谢先生。它非常有帮助。由于我对内存泄漏的了解较少,我总是害怕做 innerHTML。现在明白了。您能否为没有内存泄漏的 dom 操作提供一些参考?
    • @DineshPatra: "当删除删除任何节点时,我需要将其引用分配给其他一些值,例如 null ?" 您没有分配给“它的引用”您正在分配给变量(或属性)。仅当某些东西将该变量(或属性)保留在内存中时,您才需要这样做。但是,如果您使用完该元素,将null 分配给变量/属性在最坏的情况下是无害的,有时是有用的。回复innerHTML:我从未听说过innerHTML 的内存泄漏问题。恐怕我不知道关于这个主题的好的参考资料。
    • 非常感谢先生:
    猜你喜欢
    • 1970-01-01
    • 2013-05-29
    • 2011-02-28
    • 2015-10-08
    • 1970-01-01
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多