首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >垃圾收集和DocumentFragment

垃圾收集和DocumentFragment
EN

Stack Overflow用户
提问于 2018-08-13 22:51:04
回答 1查看 447关注 0票数 3

我读过一篇关于内存泄漏的文章,其中将垃圾收集器逻辑概括为:

  1. 垃圾收集器构建一个“根”列表。根通常是全局变量,引用保存在代码中。在JavaScript中,“窗口”对象是一个可以充当根的全局变量的示例。窗口对象总是存在的,因此垃圾收集器可以考虑它和它的所有子对象始终存在(即不是垃圾)。
  2. 所有根都被检查并标记为活动(即不是垃圾)。对所有儿童也进行递归检查。从根可以到达的所有东西都不被视为垃圾。
  3. 所有未标记为活动的内存现在都可以被视为垃圾。收集器现在可以释放该内存并将其返回到OS.

此外,MDN声明DocumentFragment不是active DOM树的一部分。

DocumentFragment接口表示没有父对象的最小文档对象。它被用作文档的轻量级版本,存储由节点组成的文档结构片段,就像标准文档一样。的关键区别在于,由于文档片段不是活动文档树结构的一部分,因此对该片段所做的更改不会影响文档,不会导致重新流,也不会导致在进行更改时可能发生的任何性能影响。

一点一点地,我开始意识到背后的逻辑,但如果有人能给我一些启发,我会非常感激的:),用下面的例子,并解释为什么:

  1. 在DOM引用被使用之后,取消DOM引用被认为是一种很好的做法。
  2. 是否需要取消对DocumentFragment和包含它的元素的引用。

代码语言:javascript
复制
function usefulFunction() {
  let existingNode = document.querySelector(`.existing`)
  
  let createdNode = document.createElement(`ul`)
  let fragment = document.createDocumentFragment();
  let browsers = ['Firefox', 'Chrome', 'Opera', 
      'Safari', 'Internet Explorer'];

  browsers.forEach(function(browser) {
      var li = document.createElement('li');
      li.textContent = browser;
      fragment.appendChild(li);
  });
    
  existingNode.appendChild(createdNode)
  createdNode.appendChild(fragment)
  
  fragment = null
  createdNode = null
  existingNode = null
}

usefulFunction()
代码语言:javascript
复制
<div class="existing"></div>

更新片段

代码语言:javascript
复制
let existingNode

function helperFunction(object) {
  let createdNode = document.createElement(`div`)
  createdNode.innerHTML = `Hello, I am a beautiful div`
  
  existingNode.appendChild(createdNode)
  existingNode = null 
}

function usefulFunction() {
  existingNode = document.querySelector(`.existing`)
  let fragment = document.createDocumentFragment();
  let browsers = ['Firefox', 'Chrome', 'Opera', 
      'Safari', 'Internet Explorer'];

  browsers.forEach(function(browser) {
      var li = document.createElement('li');
      li.textContent = browser;
      fragment.appendChild(li);
  });
      
  existingNode.appendChild(fragment)
  helperFunction()
}


usefulFunction()
代码语言:javascript
复制
<div class="existing"></div>

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-14 00:11:45

如果适当地使用局部变量,那么在使用局部变量之后,通常不需要对它们进行空化。当您离开函数的作用域时,变量就会消失,它们所引用的任何对象如果不是来自仍然在作用域中的某个变量的引用,就会变成垃圾。文档片段不是从DOM引用的,而是从变量引用的,因此当变量被销毁时,碎片可以被垃圾收集。

这是您应该谨慎使用全局变量的原因之一。它们只应用于需要长期保存的数据,例如用于保存应用程序的状态。

注意,在第一个示例代码中,取消变量对垃圾收集没有任何影响,因为它们包含的所有节点和片段都附加到DOM中。但是如果不是,这些对象在函数结束时就会变成垃圾,因此在返回之前没有必要对变量进行空化。

在第二个片段中,如果您从DOM中删除该元素,则应该对existingNode进行空化。否则,全局变量将阻止垃圾收集节点。但是,如果期望节点在应用程序的生存期内是永久的,则无需担心变量。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51831580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档