函数范围引起的JavaScript内存泄漏?

时间:2013-05-07 08:44:12

标签: javascript memory memory-leaks google-chrome-devtools v8

使用我最近发现的chrome开发工具,我使用模块化概念的应用程序将一些Module对象留在内存中,即使它们没有被我的任何其他应用程序对象直接引用。

这里的问题似乎是,它们在某些函数范围中被引用。

正如您在以下屏幕截图中看到的那样:

enter image description here

在功能范围内有很多引用。

以下是代码的一小部分,演示了在我的应用程序中如何发生这种情况的方法之一。由于在module内引用了someCallback,因此我无法删除自己的引用。

function augmentModule(core, module){

   var someCallback = function(){
      module.stop();
   };

   module.listenTo(core, "someEvent", someCallback);
}

我的问题是:

这是一个真正的内存泄漏我不得不担心,或者这个对象是否会在以后的JavaScript引擎中被垃圾收集? JavaScript引擎是否知道“此对象仅从函数和闭包范围引用,并且没有”真实“引用,因此我可以将其删除。” ?

3 个答案:

答案 0 :(得分:2)

一种方法是在模块子条目(augmenModule)中实现拆解方法。拆卸方法将取消绑定在初始化时由类设置的所有观察器函数。在处置对象以释放引用时调用您的拆解方法,并允许对相关内存进行垃圾回收。

答案 1 :(得分:2)

在您的示例中,没有实际问题。变量“模块”是从函数引用的,因此只要函数由某人保存,它就会被保留。这是绝对合法的,因为一旦调用它,你的函数就需要这个对象。当您的功能发布时,此引用将会继续。

然而,你应该意识到更微妙的事情。如果你应该在main函数中有几个闭包,它们都共享一个作用域存储。这意味着,某些引用可以保存在闭包中,甚至不需要它们:

function m(ref0, ref1, ref2, ref3) {
   var cb1 = function(){
     return ref1 + ref2;
   };
   function notCurentlyUsed(){
     return ref2 + ref3;
   };
   ref0.doSomething();
   return cb1;
}

所以,

  • ref0与闭包无关,它在m完成后释放,
  • 保留
  • ref1,cb1需要它,因此它进入由cb1保存的范围存储,
  • 保留
  • ref2,cb1和notCurentlyUsed都需要它,所以它进入由cb1保存的范围存储,
  • ref3也被保留,只需要notCurentlyUsed,但是范围结构是共享的,所以它也由cb1保存。

请注意,您可以观看开发人员工具实际保存的内容,因为函数值会公开它。

答案 2 :(得分:0)

请展开最小距离的最顶层固定器的树。 实际上,这棵树是图形的一部分,可以让你的物体保持活力。

因此,您应该通过设计您的应用程序找出保留器树中应该存活的对象,该应用程序直接或间接地保留对必须收集的“模块”对象的引用。这个参考将是问题的根源。你有很多这样的参考。在这种情况下,你必须消除所有这些。