function init() {
var bigString = new Array(1000).join('xxx');
var foo = document.getElementById('foo');
foo.onclick = function() {
// 即使`bigString`在任何地方都没有被引用,这可能会创建对`bigString`的闭包!
};
}
Eric Lippert在一段时间前写了一篇详细的博客文章,讲述了这个主题(此外还将其与VBScript进行了比较)。更准确地说,他写了关于JScript的文章,这是微软自己实现的ECMAScript,尽管与JavaScript非常相似。我想你可以假设大部分行为在Internet Explorer的JavaScript引擎中都是相同的。当然,具体实现会因浏览器而异,但我怀疑你可以将一些常见原则应用于其他浏览器。
当涉及到DOM对象时,要注意循环引用:
JavaScript中的内存泄漏模式
请记住,只有在没有对该对象的活动引用时,才能回收内存。这是闭包和事件处理程序的常见陷阱,因为某些JS引擎不会检查内部函数中实际引用的变量,并且只会保留封闭函数的所有局部变量。
这里有一个简单的例子:
一个天真的JS实现无法在事件处理程序存在时收集
bigString
。有几种解决这个问题的方法,例如在init()
的末尾设置bigString = null
(delete
对于局部变量和函数参数不起作用:delete
从对象中删除属性,而变量对象是不可访问的 - 在严格模式下的ES5甚至会抛出ReferenceError
,如果您尝试删除局部变量!)。我建议尽量避免不必要的闭包,如果您关心内存消耗。
Eric Lippert在一段时间前写了一篇详细的博客文章,讲述了这个主题(此外还将其与VBScript进行了比较)。更准确地说,他写了关于JScript的文章,这是微软自己实现的ECMAScript,尽管与JavaScript非常相似。我想你可以假设大部分行为在Internet Explorer的JavaScript引擎中都是相同的。当然,具体实现会因浏览器而异,但我怀疑你可以将一些常见原则应用于其他浏览器。
引用自该页面:
垃圾回收的主要目的是让程序员不必担心他们创建和使用的对象的内存管理,尽管当然有时候是无法避免的 - 至少对垃圾回收的工作原理有一个大致的了解总是有益的。
历史注:答案的早期版本中有一个关于
delete
运算符的错误引用。在JavaScript中,delete
运算符从对象中删除属性,与C/C++中的delete
完全不同。