我已经记录了以下Chrome错误,这导致我的代码中存在许多严重且非显而易见的内存泄漏:
(这些结果使用Chrome Dev Tools的内存分析器,它运行GC,然后获取未收集的所有内容的堆快照.)
在下面的代码中,someClass实例是垃圾回收(好):
var someClass = function() {};
function f() {
var some = new someClass();
return function() {};
}
window.f_ = f();
Run Code Online (Sandbox Code Playgroud)
但在这种情况下它不会被垃圾收集(坏):
var someClass = function() {};
function f() {
var some = new someClass();
function unreachable() { some; }
return function() {};
}
window.f_ = f();
Run Code Online (Sandbox Code Playgroud)
和相应的截图:

似乎闭包(在这种情况下,function() {})如果对象被同一上下文中的任何其他闭包引用,则所有对象都保持"活动",无论该闭包本身是否可以访问.
我的问题是关于其他浏览器(IE 9+和Firefox)的关闭垃圾收集.我对webkit的工具非常熟悉,比如JavaScript堆分析器,但我对其他浏览器的工具知之甚少,所以我无法对此进行测试.
在这三种情况中哪些将IE9 +和Firefox垃圾收集 someClass 实例?
javascript firefox internet-explorer garbage-collection google-chrome
作为ECMAScriptv5,每当控件输入代码时,enginge创建一个LexicalEnvironment(LE)和一个VariableEnvironment(VE),对于功能代码,这两个对象是完全相同的引用,它是调用NewDeclarativeEnvironment(ECMAScript v5 10.4)的结果. 3),在函数代码中声明的所有变量都存储在VariableEnvironment(ECMAScript v5 10.5)的环境记录组件中,这是闭包的基本概念.
令我困惑的是Garbage Collect如何使用这种闭包方法,假设我有以下代码:
function f1() {
var o = LargeObject.fromSize('10MB');
return function() {
// here never uses o
return 'Hello world';
}
}
var f2 = f1();
Run Code Online (Sandbox Code Playgroud)
在该行之后var f2 = f1(),我们的对象图将是:
global -> f2 -> f2's VariableEnvironment -> f1's VariableEnvironment -> o
Run Code Online (Sandbox Code Playgroud)
从我的小知识来看,如果javascript引擎使用引用计数方法进行垃圾收集,则该对象o至少有1次重新引用,并且永远不会被GCed.显然这会导致浪费内存,因为o永远不会被使用但总是存储在内存中.
有人可能会说引擎知道f2的VariableEnvironment …
我知道这里和这里关于闭包的好帖子,但似乎都没有解决我想到的特殊情况.最好用代码证明这个问题:
function foo() {
var x = {};
var y = "whatever";
return function bar() {
alert(y);
};
}
var z = foo();
Run Code Online (Sandbox Code Playgroud)
引用y中bar调用关闭,所以只要我保持z周围的垃圾收集器不会清理y.问题是 - 会发生什么x?即使它没有被引用,它是否也被该闭包持有?垃圾收集器是否会看到没有参考x并清理它?或者只要我抓住它就会x坚持y下去z?(理想的答案是引用ECMA规范.)
javascript closures garbage-collection memory-management ecmascript-5