作为回应 @Beetroot-Beetroot 的疑问(我也有同样的疑问),我进行了更深入的挖掘。我建立了
this fiddle,并使用了
chrome dev-tools' timeline 和
this article 作为指导。在这个fiddle中,两个几乎相同的处理程序创建了一个包含2个日期对象的闭包。第一个只引用
a
,第二个引用了
a
和
b
两者。尽管在两种情况下只有
a
能够真正被暴露出来(硬编码值),但第一个闭包使用的内存要少得多。无论是由于 JIC(即时编译)还是 V8 的 JS 优化魔法,我都不能确定。但从我所读到的内容来看,我会说是 V8 的 GC 在
tst
函数返回时释放了
b
,而在第二种情况下它无法释放(当
tst2
返回时,
bar
引用了
b
)。我感觉这并不是那么离奇,我也不会惊讶地发现 FF 甚至 IE 也会以类似的方式工作。
我刚添加了这个可能不相关的更新,为了完整起见,也因为我觉得链接到谷歌的 dev-tools 文档是一种增值。
这有点取决于情况,简单来说:只要您无法再引用classInstance
变量,它就应该被垃圾回收,而不管它自己是否存在循环引用。我已经测试了很多类似于您在此描述的构造。也许 值得一看
我发现闭包和内存泄漏并不常见或容易发生(至少不再是这样)。
但正如被接受的答案所说:几乎不可能知道什么时候代码会泄漏。
再次阅读您的问题,我想说:不,您不会泄漏内存: classInstance
变量没有在全局范围内创建,而是被传递给各种函数(因此各种范围)。每次函数返回时,这些作用域都会消失。如果已将classInstance
传递到另一个函数/作用域中,则不会对其进行GC处理。但是,只要最后一个引用classInstance
的函数返回,对象就会被标记为GC。当然,它可能是循环引用,但是这是一个无法从任何地方访问的引用,除了它自己的作用域。
您实际上不能称之为闭包:闭包发生在某种形式的外部范围暴露的情况下,这在您的示例中并未发生。
我很糟糕地解释这种东西,但是简单概括一下:
var foo = (function()
{
var a, b, c, d;
return function()
{
return a;
}
})();
GC将释放内存
b、
c和
d的引用:它们已经超出了作用域,无法访问它们...
var foo = (function()
{
var a, b, c, d;
return function()
{
a.getB = function()
{
return b;
}
a.getSelf = function()
{
return a;
}
return a;
}
})();
foo = new Date();
在这种情况下,由于明显的原因,
b
也不会被GC回收。
foo
暴露了
a
和
b
,其中
a
是包含循环引用的对象。但是,一旦
foo = new Date()
,
foo
就失去了对
a
的任何引用。当然,
a
仍然引用自身,但是
a
不再被
暴露:它可以引用任何它想要的东西。大多数浏览器都不会关心,会GC回收
a
和
b
。事实上,我已经检查过Chrome、FF和IE8,它们都完美地GC了上面的代码...没问题。