我是否对V8是否对范围内的各个变量的内容进行垃圾收集感兴趣,或者是否只对整个范围进行垃圾收集感兴趣?
所以,如果我有这个代码:
function run() {
"use strict";
var someBigVar = whatever;
var cnt = 0;
var interval = setInterval(function() {
++cnt;
// do some recurring action
// interval just keeps going
// no reference to someBigVar in here
}, 1000);
someBigVar = somethingElse;
}
run();
V8垃圾会收集someBigVar
吗?由于run()
回调,setInterval()
中的闭包仍然存在,显然cnt
变量仍然被使用,因此run()
的整个范围不能被垃圾回收。但是,someBigVar
没有实际的持续参考。
V8是否只垃圾一次收集整个范围?那么,run()
的范围不能被垃圾收集,直到间隔停止?或者它是否足够智能垃圾收集someBigVar
,因为它可以看到间隔回调中没有实际引用someBigVar
的代码?
仅供参考,这里是interesting overview article on V8 garbage collection(它没有解决这个具体问题)。
答案 0 :(得分:2)
是的,确实如此。仅保留在闭包内实际使用的变量。否则,闭包必须捕获外部范围中定义的所有内容,这可能很多。
唯一的例外是如果在闭包内使用eval
。由于没有办法静态地确定eval
的参数所引用的内容,引擎必须保留所有内容。
以下是使用weak模块(使用--expose-gc
标志运行)演示此行为的简单实验:
var weak = require('weak');
var obj = { val: 42 };
var ref = weak(obj, function() {
console.log('gc');
});
setInterval(function() {
// obj.val;
gc();
}, 100)
如果封闭内部没有ref
的引用,您会看到gc
已打印。