V8是否在一个范围内的单个碎片上进行垃圾回收?

我感兴趣的是V8是否在一个范围内的单个variables的内容上进行垃圾回收,还是只在整个范围内进行垃圾回收?

所以,如果我有这个代码:

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垃圾收集一些someBigVarrun()的闭包因为setInterval()callback而保持不变,显然cntvariables仍在使用,所以run()的整个范围不能被垃圾收集。 但是,没有实际的持续参考一些someBigVar

V8只有垃圾一次收集整个范围吗? 那么, run()的范围不能被垃圾回收,直到间隔停止? 或者是足够聪明的垃圾收集someBigVar因为它可以看到在实际引用someBigVar的区间callback没有代码?

仅供参考,这里有一个关于V8垃圾收集的有趣的概述文章 (它没有解决这个具体的问题)。

是的,它确实。 只有在闭包中实际使用的variables才被保留。 否则,封闭必须捕获在外部范围内定义的所有东西,这可能是很多的。

唯一的例外是如果你在闭包中使用eval 。 由于没有办法静态确定, eval的参数引用什么,引擎必须保留一切。

下面是一个简单的实验来演示使用弱模块(使用--expose-gc标志运行)的行为:

 var weak = require('weak'); var obj = { val: 42 }; var ref = weak(obj, function() { console.log('gc'); }); setInterval(function() { // obj.val; gc(); }, 100) 

如果closures内部没有引用ref ,你会看到gc打印。