1

我正在开发一个大量使用 Javascript 并包含大量 DOM 操作的项目。随着代码的增长,我注意到有时在Internet Explorer (9) 下页面加载时 Javasript 执行会有延迟(大约 1-2 秒)。这种延迟从未在 Firefox 上发生过。

例如:

// the actual code contains much more stuff
$("body").append("<p>paragraph</p>");

尽管它p是动态生成的,但它应该在现代浏览器上的页面加载后立即看到。但在 IE 上,有时我可以清楚地看到在所有静态内容加载p后被添加,这使得整个页面跳跃。

如果我重新启动 IE,延迟就消失了。但是,如果已经完成了大量的 DOM 操作,它会在下一页刷新时再次发生。

所以我在想这是否是memory leak由于我很少取消对象引用引起的。

var foo = $("#foo");
foo.on("click", function() {
    var bar = '<div id="bar">bar</div>';
    $("body").append(bar);
    // nullify bar
    bar = null;
});
// nullify foo
foo = null;

问题:

  1. 我应该像上面的例子一样在使用完每个对象引用后取消它们吗?

  2. 如果 Q1 的答案是否定的,我应该在什么时候或在什么情况下使对象引用无效?

  3. 除了无效之外,我还能做些什么来防止内存泄漏?

PS:几年前我读过一些类似的问题,它们主要针对 IE 6/7。

4

1 回答 1

4

我应该像上面的例子一样在使用完每个对象引用后取消它们吗?

不,那是矫枉过正。

如果 Q1 的答案是否定的,我应该在什么时候或在什么情况下使对象引用无效?

当您不再需要它但它在仍然存在的功能范围内时。在您的示例中,foo可以从单击处理程序中引用,因此只要处理程序附加到 DOM,它就不会被垃圾收集。然而,没有理由取消bar

除了无效化之外,我还能做些什么来防止内存泄漏?

  • 根本不要使用变量。在您的示例中,您可以简单地使用链接:$("#foo").on(…);
  • 如果它们与使用它们的执行上下文无关,请在不同的范围内声明您的处理程序函数:
$(document).ready(function() {
    var foo = $("#foo");
    foo.on("click", showBar);
    // do anything else with `foo`
});
function showBar() {
    var bar = '<div id="bar">bar</div>';
    $("body").append(bar);
});

几年前我读过一些类似的问题,它们主要针对 IE 6/7。

这是因为 IE6/7 在其垃圾收集器中存在一些错误(javascript、循环引用和内存泄漏MSDN 文章)。然而,上面提到的技术与此无关,它们假设一个正确工作的 GC。通过优化 GC,甚至可能不需要它们,例如 V8 确实收集了实际上在范围内但不再使用的变量(调试显示模块模式:函数在调用之前不在范围内?)。

于 2013-02-23T17:41:59.593 回答