V8是否对范围的各个部分进行垃圾收集?

时间:2015-04-24 20:22:49

标签: javascript node.js google-chrome garbage-collection v8

我是否对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(它没有解决这个具体问题)。

1 个答案:

答案 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已打印。