这是垃圾收集?

时间:2014-01-15 00:09:33

标签: javascript garbage-collection

我确信之前曾有过类似的问题,但是没有回答我问题的大量类似问题迫使我自问。

假设您有以下代码:

(function() {
    "use strict";
    var somearray=[1, 2, 3];
    for(var i=0; i<somearray.length; i++) {
        //do something
        }
    function loop() {
        //do something repeatedly
        requestAnimationFrame(loop);
        }
    loop();
    })();

由于变量i在与永久循环相同的范围内定义,即使未使用它也会继续存在,等待它最终可能被使用的可能性?或者JavaScript(特别是Chrome的V8)垃圾收集器是否足够聪明,以确定它是否会被使用?

我知道我可以在某个地方添加console.log(i)然后i只要它被引用就会继续存在,但是它会继续存在于一个继续存在的范围内吗?

1 个答案:

答案 0 :(得分:2)

这不是关于垃圾收集器的问题,而是关于闭包是否优化的问题。执行环境的闭包优化器可能确定嵌套函数不引用(关闭)变量,然后从闭包环境中忽略它们。如果是这样的话,那么他们就是收集的候选人。如果未运行闭包优化器,或者它确定引用了isomearray,或者它无法确定isomearray的生命周期,那么它们将不会根据封闭环境的要求收集。

一个函数有一个隐式环境,它包含封闭函数中的所有局部变量(以及包含它的所有函数)。此环境将捕获这些变量引用的任何对象。闭包优化器静态分析函数以确定是否可以修剪环境以忽略未引用的变量。如果变量从环境中删除,则一旦函数调用结束,它们就是候选集合。

所有现代JavaScript引擎都有一个闭包优化器。

可能禁用或限制闭包优化器的一些常见问题包括处于调试模式,使用直接eval(),使用arguments数组,使用不推荐使用的功能,例如caller

正如您所看到的,它显然取决于\\do something repeatedly的作用以及执行代码的上下文。

无论\\do something repeatedly做什么,确保不捕获它们的一种方法是确保它们不再在范围内。一个立即执行的函数将执行此操作,因此将代码更改为

(function() {
  "use strict";
  (function() {
    var somearray=[1, 2, 3];
    for(var i=0; i<somearray.length; i++) {
      //do something
    }
   })();
  function loop() {
    //do something repeatedly
    requestAnimationFrame(loop);
  }
  loop();
})();

将确保数组不会留在内存中。