JavaScript:我应该担心2011年的内存泄漏吗?

时间:2011-09-11 20:58:45

标签: javascript memory-leaks

JavaScript中的内存泄漏主题并不常见。然而,我偶然发现了2007年写的this article。作者说:

  

Internet Explorer和Mozilla Firefox是最常用的两种Web浏览器   通常与JavaScript中的内存泄漏有关。

2011年我是否仍然担心JavaScript内存泄漏?如果是这样,我应该注意什么?

5 个答案:

答案 0 :(得分:12)

是的,内存泄漏肯定是JavaScript中的问题,因为循环引用确实是可能的。内存泄漏的一个非常常见的来源是使用闭包。例如,请考虑:

var outerFunction = function(param1, param2, param3) {
     var innerFunction = function() {};
     return innerFunction;
};

上述内容可能会泄漏参数,因为innerFunction包含对其构造范围的引用,其中包含该框架的参数。

虽然在许多台式计算机上很容易忽视这些类型的东西,但是RAM很多,这实际上在内存有限的设备上非常明显(例如手机或机顶盒)框)。作为一个轶事的例子,一些仍然未命名的网站曾经经常从我的电视访问时崩溃,而电视的内存非常有限。

请注意,这些问题与Web开发人员编写的JavaScript代码有关。尽管可能,底层JavaScript解释器中的内存泄漏问题远远不是问题,并且不是Web开发人员可以合理关注的内容,因为这是浏览器编写者的工作。

答案 1 :(得分:12)

一个优秀的javascript开发人员会意识到可能导致内存泄漏的各种设计模式,并且你会避免编写任何可能导致你编码的几乎所有页面都出现漏洞的内容。

例如,在javascript变量中保留对任何DOM对象的引用将使该DOM对象在内存中保持活动状态,即使它已从DOM中删除很久并且您打算将其释放。

实际上,泄漏只在某些情况下很重要。这是我特别担心的地方:

  1. 我在计时器上重复做的任何事情,特别是如果它可以长时间保持运行状态。例如,如果您有一个可能永远循环的幻灯片,您必须确保幻灯片中的任何内容都不是JS或DOM对象的累积泄漏。
  2. 一个像应用程序一样工作的网页,用户可能会长时间停留在同一页面上,与页面交互,执行ajax调用等等...例如,一个Web邮件应用程序可能是打开的并且在相同的实际浏览器文档在很长一段时间内进行大量的用户和服务器交互。
  3. 定期创建和销毁大量DOM元素的网页,例如经常使用ajax获取大量新HTML的内容。
  4. 我并不担心泄漏的地方:

    1. 一个网页,没有用户可以进行的长时间交互。
    2. 在加载某个其他页面或重新加载此页面之前很长时间没有停留在屏幕上的网页。
    3. 我一直关注的一些关键事项。

      1. 在创建/销毁DOM元素时包含对DOM元素的引用的任何持久JS变量或属性。
      2. DOM对象的任何属性,包含对其他DOM对象的引用或对包含对其他DOM对象的引用的JS对象的引用(这可以在JS / DOM之间创建循环引用和交叉引用,而某些旧版浏览器无法释放它们)。
      3. 我加载临时使用的任何大型数据结构。我确保不会保留对这些大型数据结构的引用。
      4. 任何数据缓存。确保没有任何真正大的内容被缓存,您不希望缓存。确保所有反复使用的缓存不会永远累积,并具有某种老化机制来摆脱旧对象。

答案 2 :(得分:7)

NO。

更完整的答案:也许吧。你这么模糊地问这个事实是一个强烈的信号,你个人不太可能担心。

在实践中,绝大多数JavaScript代码根本不担心它,并且不需要担心它,因为只有在特定情况下,页面中的内存泄漏最终会影响用户。浏览器和框架很好地覆盖了你的屁股。

您只需回答几个问题:

问:您是否支持使用JavaScript的丰富单页应用程序?

如果没有,那么不要浪费你的时间担心。如果您(或您的QA或您的客户)发现页面存在内存过量使用问题,请在出现问题时进行修复。

问:您是否需要支持移动设备,并且您使用了大量的JavaScript?

移动设备的内存有限,需要特别小心。

如果您正在开发一个JavaScript繁重的应用程序,而您需要担心内存使用情况,那么......

对于导致JavaScript对象和DOM对象永远不会被垃圾回收的对象的“脏”引用问题对于某些类型的JavaScript应用程序很重要。永远成长的缓存,意外的全局引用以及闭包内的意外引用可能是个问题。

Chrome网站检查器中的堆快照工具可以提供帮助。

这是一个git项目,它有一个有用的文档并可以遍历javascript对象:https://github.com/tlrobinson/leakhelper

还有其他工具可以帮到你,但我随着时间的推移编写了自己的工具:  1.我们的框架标记了已删除的小部件,因此我编写了代码来从窗口或文档中查找所有数组和对象,以查找被选对象的路径(javascript代码无法执行闭包,但它确实帮助找到了一些泄漏)。  2.我使用的另一个技巧是当widget x被删除时,我执行x.leakhelper = window.createElement('leakhelper')和setAttribute小部件的oid,但不将元素添加到文档中。如果DOM元素垃圾收集,则窗口小部件必须在某处悬挂引用它。在IE中使用window.collectGarbage()来强制GC,并使用sIEve来检测泄漏的DOM元素(我发现sIEve非常有用)。

过时的问题:您是否需要强烈支持IE6或IE7并且您大量使用JavaScript?您以前阅读的大多数可怕泄漏仅发生在< IE8。如果您支持IE6或IE7,那么您需要好运和坚持(所有框架都会泄漏,并且很难编写甚至没有完美框架的代码 - 我最终编写了我自己的IE防漏代码用于我们的生产用途对于IE6 / 7用户)。即使关闭页面,IE6 / IE7泄漏也会持续 - 这就是为什么它们如此令人讨厌。

答案 3 :(得分:1)

好吧,人们仍然使用旧版本的IE。所以要注意循环引用,因为IE有严重的问题。我相信这方面的常见错误是在一个闭包中引用一个HTML元素,该闭包位于该元素的事件处理程序中。只需将引用该元素的变量设置为null即可。

答案 4 :(得分:1)

这实际上取决于两件事 -

  1. 应用程序的平均运行时间预期。在线商店主页上的简单jquery灯箱或carusel可能会泄漏(并且通常会,因为它们的编码非常严重),但没有人会注意到(因为页面在几分钟或更短的时间内关闭或刷新)。但Node.js服务器, full-ajax 社交网络,浏览器游戏或在线IDE - 可以连续运行数小时甚至数天。

  2. 您的应用程序的
  3. I / O复杂性。您接触DOM,XHR /网络,文件,DOM / UI事件的次数越多,重绘屏幕的次数就越多(无论是canvas,html还是svg) - 泄漏风险越大,内存占用(这不是泄漏)并且遇到浏览器错误。

  4. 对你而言,好事是 - 这两件事情彼此相关。所以,你要么就像没有明天那样编写铲码,要么就工程师的性能,耐力和稳健性来写。

    p.s。:如果你必须支持IE8-,你还没有在2011年。所以你只需要担心,就像过去一样。