javascript - V8 是否对作用域的各个部分进行垃圾回收?

标签 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() 的范围在interval 停止之前不能被垃圾回收?还是因为它可以看到间隔回调中没有实际引用 someBigVar 的代码,所以它足够聪明地进行垃圾收集 someBigVar

仅供引用,这是一个 interesting overview article on V8 garbage collection (它没有解决这个具体问题)。

最佳答案

是的,确实如此。仅保留在闭包内部实际使用的变量。否则闭包必须捕获在外部作用域中定义的所有内容,这可能会很多。

唯一的异常(exception)是在闭包中使用 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

关于javascript - V8 是否对作用域的各个部分进行垃圾回收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29856803/

相关文章:

javascript - 为什么在 Chrome 中存储到变量 "name"的数组会转换为字符串?

javascript - chrome 弹出窗口关闭时的事件

javascript - chrome.tabs.captureVisibleTab 在 chrome.tabs.update 之后作为同步回调失败?

javascript - 在图表 js 中只想要线条而不是它下面的区域

javascript - JS - 选择输入字段后禁用事件监听器

angularjs - Amazon S3浏览器直接上传唯一文件名

node.js - 提供权限请求建议 (Dialogflow V2)

node.js - 中途停止 promise 链

javascript - 如何使用javascript计算元素的点击次数

javascript - 使用 jQuery 导航函数数组