JavaScript中的'remove'方法和'removeChild'方法有什么区别?

18

我已经创建了一个HTML页面,以了解如何删除元素的工作原理。

代码:

<html>
  <head>
    <script>
      var childDiv = null;
      var parent1 = null;
      var parent2 = null;
      function init() {
        childDiv = document.getElementById("child");
        parent1 = document.getElementById("parent1");
        parent2 = document.getElementById("parent2");
      }

      function rem() {
        if (childDiv) {
          childDiv.remove();
          alert("child removed");
        } else {
          alert("child does not exist");
        }
      }

      function remChild() {
        if (childDiv){
          if (parent1.children.length > 0) {
            parent1.removeChild(childDiv);
            alert("child unbound from parent");
          } else {
            alert("child exists but is not bound to parent");
          }
        } else {
          alert("child does not exist");

        }
      }

      function ins() {
        if (childDiv) {
          parent2.appendChild(childDiv);

          alert("child inserted to another parent");
        }
      }
    </script>
  </head>
  <body onload="init()">
    <div id="parent1">
      <div id="child"></div>
    </div>
    <div id="parent2"></div>
    <button onclick="rem()">remove</button>
    <button onclick="remChild()">removeChild</button>
    <button onclick="ins()">insert</button>
  </body>
</html>

在这里,我尝试两种方法删除“child” div:

  1. 调用“child” div上的“remove”方法

  2. 调用“parent1”节点上的“removeChild”方法

但无论哪种情况,该节点实际上都没有被删除。我总是可以将“child” div插入到“parent2”中。

我理解在第二种情况下,“child”已解除与“parent1”的绑定,但实际上没有被删除。但在第一种情况下,“child”不是永久删除了吗?

当尝试插入不存在的元素时,我不应该收到错误吗?

请解释。

如果在调用元素上的“remove”后该元素仍存在:

  1. 'remove'与'removeChild'有何不同?就我所看到的,这两种方法都只是将子项从父项中解绑,但元素仍占用内存。

  2. 是否有任何方法确保元素实际上已从内存中删除?

2个回答

39

节点实际上并未被删除

可能会让人困惑的原因是您认为删除一个元素意味着杀死或销毁它。

enter image description here

但事实上,删除的概念基本上是打破子元素和父元素之间的关系。这只是一种分离。

enter image description here

插入一个不存在的元素时,我不应该得到错误吗?

不会,因为它仍然存在。

removeremoveChild有何不同?

remove只需要对子元素的引用。removeChild需要对父元素和子元素的引用。结果相同。

有没有方法确保元素已从内存中实际删除?

没有。您只能取消引用它,并希望有一个垃圾收集器可以检测到该对象未被引用,然后将其删除。


假设我们有一个内联箭头函数附加到节点上,那么附加到节点的事件监听器会发生什么?现在没有直接的方法使用removeEventListener,垃圾回收器会自动删除它,还是它会一直存在于内存中(我已经阅读了几篇文章)。谢谢。 - Wasit Shafi
@WasitShafi,除非您保留对匿名内联事件处理程序函数的引用,否则无法删除它。它是否添加到dom中并不重要。如果它是强引用,则不应该被垃圾回收。如果它是弱引用,则应该被垃圾回收。您可以测试一下以确保这一点。将一个匿名函数添加到单击事件中,然后分离节点。也许检查一下内存大小,然后稍后再添加节点。看看单击事件是否仍然存在,并再次检查内存大小。1/2 - 1.21 gigawatts
它的工作方式是,如果没有指向该函数的引用,则垃圾回收应该会删除对象。如果存在强引用,例如处理程序在文档主体上声明,则它不应被垃圾回收。如果有一种方法触发垃圾回收(那就太好了),你就可以看到结果。我的猜测和经验是,节点将在整个浏览器会话期间保留在内存中,但我目前无法证明这一点。我知道移动浏览器可能会更频繁地尝试GC。而且它在不同的浏览器之间可能会有所不同。有关详细信息,请提出单独的问题。2/2 - 1.21 gigawatts

12
remove 是一个新的函数,它是一个快捷方式,可以更简单地移除一个元素,而不必查找父节点。不幸的是,在旧版本的Internet Explorer上不可用,所以,除非你不想支持这个浏览器,否则你将不得不使用removeChild或使用polyfill
保留子元素在内存中的原因是,你的代码保留了对它的引用。
如果你这样做:
childDiv = null;

那么就没有指向该对象的引用了,浏览器可以释放这块内存。


1
我尝试使用'removeChild'移除了'child'并且也删除了对它的引用。这次元素被永久删除,无法再获取'child'。因此,'removeChild'不仅是将元素从父级解绑,而实际上是将其删除?我之所以能够获取'child'是因为我在代码中保留了引用?所以这只是关于保持引用计数:就像跟踪指向对象的指针数量一样?一旦引用计数为0,内存就会被释放? - Prasoon
1
只是提供信息,'remove' 在IE 11上可用。 - Prasoon
更广泛地说,任何无法访问的值(使用引用或DOM函数)都可以被引擎释放(通常会被释放)。 - Denys Séguret

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接