我正在开发一个大量使用Javascript的项目,其中包括大量DOM操作。随着代码的增长,我注意到在InternetExplorer(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;
问题:
当每个对象引用都像上面的例子一样被使用时,我应该取消它们吗?
如果Q1的答案是否定的,我应该在什么时候或在什么条件下取消对象引用?
除了无效之外,我还能做些什么来防止内存泄漏?
附言:几年前我读过一些类似的问题,它们大多是针对IE 6/7的。
当每个对象引用都像上面的例子一样被使用时,我应该取消它们吗?
不,那太夸张了。
如果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确实收集了实际在范围内但不会再次使用的变量(调试揭示模块模式:函数在调用之前不在范围内?)。