清除不再引用的元素,并且从未添加到文档中

Bra*_*rad 5 javascript dom

假设我创建了一个新元素:

let canvas = document.createElement('canvas');
Run Code Online (Sandbox Code Playgroud)

现在,稍后在脚本中,我删除任何JS引用.

canvas = null;
Run Code Online (Sandbox Code Playgroud)

canvas 元素本身是否仍然存在,记忆?或者它会像任何其他未引用的对象一样被垃圾收集?请注意,我实际上没有将其添加到文档中.

小智 5

<canvas>元素本身是否仍然存在并占用内存?还是像其他未引用对象一样被垃圾回收?

是的,它暂时仍然存在。是的,它将在适当的时候被垃圾收集。

其他张贴者似乎对canvas 变量<canvas> 元素之间GC行为的差异感到有些困惑。变量分配在堆栈上,而不是堆上。只要它们在范围内,它们就会在堆栈上占用少量内存。由于它们处于调用链中,因此它们仍然在范围内。当函数退出并弹出堆栈框架时,它们使用的内存将释放。

像其他对象一样,元素也分配在堆上,并进行垃圾回收。当不再引用它们时,它们将被GC。该<canvas>元素可以作出不再被引用或者通过设置任何变量引用它null或别的东西,(唯一)变量引用它去的范围了。

当然,还有另外一种情况涉及变量的内存管理,即闭包。只要封闭的函数处于“范围内”(换句话说,就是引用该函数),则被封闭的变量将继续占用(少量)内存。在闭包中的函数超出范围之前,此类变量的值(无论是DOM元素还是JS对象或其他任何值)都不会且无法进行GC。小例子:

function a() {
  const div = document.createElement('div');
  return function() {
    console.log(div);
  };
}

function b() {
  const func = a();
}
Run Code Online (Sandbox Code Playgroud)

b输入的,分配存储在堆栈上funca会被调用,这将创建DOM元素并返回内部函数。此时,div保持分配状态,因为它已被内部函数关闭并在内部函数中被引用。DOM元素保留在堆中。一旦b退出,该变量func就会从堆栈框架弹出,这意味着不再有任何内容引用闭包函数。这意味着div范围已不再。反过来,这意味着不再引用该元素,并且将对其进行GC(最终)处理。

最重要的是,您无需担心任何这些。它可以正常工作,除非出现病理情况或引擎错误。

  • 不,`document.createElement`不会做类似的事情。如果未引用,将进行GC处理。即使向其添加事件处理程序也不会改变-事件处理程序挂在元素上,因此,如果不再引用该元素,则元素及其事件处理程序都将是GC的。 (3认同)
  • 感谢您的解释。我知道闭包,什么也不知道,我只是不确定`document.createElement`是否对该元素做了任何奇怪的事情,将其附加到我无法控制的某处,以防止以后收集它。 (2认同)