javascript - 关闭未使用变量的内存泄漏

标签 javascript

我想了解在哪些情况下不再使用的变量存储在闭包中并导致内存泄漏。我最喜欢的结果是“没有”,但事实似乎并非如此。

据我了解,一旦在另一个函数中声明了一个函数,它的内部 [[scope]] 就会被分配其封装函数的 LexicalEnvironment。这个 LexicalEnvironment 具有引用局部变量和此时的整个作用域链。这基本上包括函数可以访问的所有自由变量(根据我对 lostechies, javascript closures explained 的理解)。

这里出现了第一个问题:这应该意味着只要函数存在,就可以访问所有这些变量。例如。以下应该已经泄漏:

function a() {
    let big = new Array(1000000).join('*'); //never accessed
    //function unused() { big; }
    return () => void 0;
}
 
let fstore = [];
function doesThisLeak() {
  for(let i = 0; i < 100; i++) fstore.push(a());
}

doesThisLeak();

幸运的是,在我的 Firefox 上似乎并非如此。我收到了一些关于为什么这不会泄漏的解释,从“抖动很聪明”到“LexicalEnvironment 是一种记录类型,这意味着 GC 可以收集未使用的变量”。我仍然不知道两者是否正确,这是否不会在所有现代运行时泄漏以及为什么。

经过进一步研究,我发现auth0, four types of leaks in javascript (遗憾的是,似乎没有可跳转到的 html id,相关部分是“4:闭包”),它展示了一种欺骗收集未使用变量的聪明东西的方法。在上面的片段中,当只是取消注释“未使用”函数时,我没有看到 RAM 使用率再次下降(已经注意到它可能是 GC 由于其他原因而没有运行。但是,到目前为止,我假设它泄漏。我还被告知这仅限于 firefox,但它似乎在 chrome 中产生了类似的行为)

这个例子(万一它真的做了我相信它做的事)表明完全未使用的变量可能由于同一范围内的函数声明而泄漏。

总结我的问题:

  1. 在上面的代码片段中,收集“big”的原因是什么(当评论“unused”时),这是否发生在所有现代运行时?
  2. 假设带有“未使用”函数的示例未注释泄漏,那么避免此类意外泄漏的最佳做法是什么?还有吗?我已经得到了将函数末尾未进一步使用的所有局部变量置空的建议,但是,这看起来非常丑陋。我担心使用临时变量进行预计算和不小心泄漏。

PS:很难确定这个问题是否已经在有关闭包的内存泄漏问题的丛林中提出过。

最佳答案

编译器可以检查返回函数的代码以查看它引用了哪些自由变量,并且只有那些变量需要保存在闭包中,而不是整个 LexicalEnvironment。您可以通过检查 Javascript 调试器中的闭包来了解这一点。

function a() {
  let big = new Array(1000000).join('*');
  let small = "abc"; // is accessed
  return (x) => small + x;
}

fun = a();
console.dir(fun);

function b() {
    let big = "pretend this is a really long string";
    function unused() { big; }
    return () => void 0;
}

fun = b();
console.dir(fun);

当您在调试器中展开第一个函数时,您会在 Closure 属性中看到 small,但看不到 big。不幸的是,Chrome 编译器似乎不够聪明,无法检测到变量何时在未返回的未使用函数中被引用,因此不需要保存,所以我们在 b 中发现了泄漏()

enter image description here

任何没有保存在闭包中的数据都会变成垃圾并且可以被收集,所以它不会泄漏。

关于javascript - 关闭未使用变量的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38838071/

相关文章:

javascript - 如何循环枚举值以在单选按钮中显示?

javascript - 当 readonly=true 时,为什么使用 Javascript 分配给 Primefaces inputText 小部件的值不会发送到服务器?

javascript - 在 ComboBox 的焦点上而不是在键入时发送 Ajax 请求

javascript - 使用 angularJS 进行带有类别和标签的实时搜索

javascript - 嵌套 for 循环功能

javascript - 如何使用 angular-http-auth 传递凭据?

javascript - Meteor 不呈现 css 并在使用外部 DDP Meteor 实例时不断重新加载应用程序

javascript - 在 Express static 中使用中间件在 Node js 中不起作用

javascript - Jquery 显示/隐藏 div onclick 单选按钮 - 根本不起作用

javascript - 通过自动完成功能输入相互依赖的文本