ES6 const会影响垃圾回收吗?

ben*_*les 18 javascript garbage-collection const ecmascript-6

在Kyle Simpson的新标题中,你不了解JS:ES6及更高版本,我找到以下代码片段:

警告将对象或数组指定为常量意味着在该常量的词法范围消失之前,将无法对值进行垃圾回收,因为对该值的引用永远不会被取消.这可能是可取的,但如果不是你的意图,要小心!

(摘录自:Simpson,Kyle."你不了解JS:ES6及其他."O'Reilly Media,Inc.,2015-06-02.iBooks.这些材料可能受版权保护.)

据我所知,他没有对此进行扩展,而且谷歌上的10分钟没有任何结果.这是真的,如果是这样,"对价值的引用永远不会被取消"的含义究竟是什么意思?我养成了宣​​称不会改变的变量的习惯const,这是真正的具体性能/记忆术语中的坏习惯吗?

jfr*_*d00 18

警告将对象或数组指定为常量意味着在该常量的词法范围消失之前,将无法对值进行垃圾回收,因为对该值的引用永远不会被取消.这可能是可取的,但如果不是你的意图,要小心!

那个音符听起来比一个必要的警告(可能甚至有点傻),并试图在这种情况下做出某种特殊情况.

使用const变量声明,您无法将变量分配给变量""null清除其内容.这实际上是内存管理方面的唯一区别.根据是否声明,自动垃圾收集完全不受影响const.

因此,如果您希望以后能够出于任何原因更改变量的内容(包括手动删除对某些内容的引用以允许更快地收集垃圾),那么请不要使用const.这与使用或不使用的任何其他原因相同const.如果您希望能够在将来的任何时间更改变量包含的内容(出于任何原因),请不要使用const.对于了解const其用途的人来说,这应该是完全明显的.

把垃圾收集作为一个特殊情况,当不使用时,const对我来说似乎很愚蠢.如果您希望能够清除变量的内容,那么这意味着您要修改变量,所以duh,不要使用const.是的,手动启用可能在持久范围/闭包中捕获的大型数据结构上的垃圾收集是您可能希望在将来更改变量的一个原因.但是,这只是数百万个原因中的一个.所以,我再重复一次.如果您希望将来因任何原因更改变量的内容,请不要将其声明为const.

垃圾收集器本身并没有把一个const变量或它指向的不是任何不同的内容varlet变量.当它超出范围并且不再可访问时,其内容将有资格进行垃圾回收.

const有许多优点.它允许开发人员声明一些意图,即此变量指向的内容不会被代码更改,并且可能允许运行时进行一些优化,因为它知道变量的内容无法更改.并且,它可以防止恶意或意外代码不断更改该变量的内容.在适当的情况下使用时,这些都是好事.一般来说,你应该const尽可能多地使用.

  • @KyleSimpson - 这个答案有什么不准确之处?这里的问题是关于`const`变量.您链接的答案讨论了闭包.这个问题以多种方式预测GC的闭包,包括最后两个句子.但是,底线 - 如果你想分配给变量,不要使它成为`const`.如果您不需要分配它并希望它受到保护,请将其设为`const`.没有比这更复杂的了. (3认同)
  • @KyleSimpson - `const`本身并不会改变垃圾收集.如果要手动删除变量指向的引用,则不要使该变量为"const". (3认同)
  • @KyleSimpson - 如果它是`const`或`var`,你认为GC对变量有什么不同吗?是的,程序员必须使用`const`或`var`做不同的事情,而不是GC.并且,是的,如果你想在将来的某个时候将变量设置为null以使某些东西适合GC,那么不要使用`const`.咄.我的回答的第二段已经说明了.你认为我之前评论的哪一部分是错的?仅供参考,我不同意你的观点,但我没有回答你的回答. (3认同)
  • +1"傻":-) (2认同)
  • 这个答案不准确。请参阅此答案:http://stackoverflow.com/questions/31686412/does-es6-const-affect-garbage-collection/38318597#38318597 (2认同)
  • @KyleSimpson - 变量指向的内容将在完全相同的时刻进行垃圾收集,无论变量是用`const`还是用`var`声明的.如果你想在将来的任何时候出于某种原因修改该变量的内容,那么不要使用`const`. (2认同)

Ber*_*rgi 9

不,没有性能影响.本文指的是通过"取消设置"变量来帮助垃圾收集器(很少需要)的做法:

{
    let x = makeHeavyObject();
    window.onclick = function() {
        // this *might* close over `x` even when it doesn't need it
    };
    x = null; // so we better clear it
}
Run Code Online (Sandbox Code Playgroud)

如果您声明x为a,那么显然不可能这样做const.

变量的生命周期(当它超出范围时)不受此影响.但是如果垃圾收集器搞砸了,常量将始终保持初始化的值,并防止垃圾收集,而普通变量可能不再容纳垃圾收集器.

  • @KyleSimpson:在这种情况下,我会说性能含义是因为缺少`null`赋值,而不是因为变量被声明为`const` :-)不,我没有低估你的答案. (3认同)
  • @KyleSimpson:答案中的`someCoolNumbers`和我的`x`之间的区别在哪里?你(显然)无法明确地使`const`无效的观点是相同的. (2认同)
  • @KyleSimpson:当然,如果函数关闭`x`(并且存在某些点,对该函数的调用不再需要`x`),即使GC不天真,也建议帮助垃圾收集器.但我仍然认为这种情况很少发生,大多数情况下闭包本身都是收集的,或者值不大,因此没有内存泄漏实际上*需要*无效. (2认同)
  • @KyleSimpson:丢失它的可能性更大的原因是作者忘记了它……如果他没有忘记它,他会把const变成“ let”。或者它可能不会丢失,在const赋值上抛出异常,炸毁应用程序-并且没有更多的内存可能泄漏:-P (2认同)

Jos*_*eph 8

垃圾收集器(GC)工作的方式是什么东西被什么都引用("无法到达")时,GC可以安全地说不再使用某些东西并回收那些东西所使用的内存.

能够替换变量的值允许删除对值的引用.但是,不像var,const不能重新分配一个值.因此,无法从引用该值中删除该常量.

当常量变为"超出范围"时,可以回收常量,如变量,就像函数退出时一样,并且内部的任何内容都不会形成闭包.


Kyl*_*son 6

我的书中的那个注释指的是这样的情况,你希望能够在其父范围的生命周期结束之前手动创建值GC'able:

var cool = (function(){
   var someCoolNumbers = [2,4,6,8,....1E7]; // a big array

   function printCoolNumber(idx) {
      console.log( someCoolNumbers[idx] );
   }

   function allDone() {
      someCoolNumbers = null;
   }

   return {
      printCoolNumber: printCoolNumber,
      allDone: allDone
   };
})();

cool.printCoolNumber( 10 ); // 22
cool.allDone();
Run Code Online (Sandbox Code Playgroud)

allDone()在这个愚蠢的例子中,函数的目的是指出有时你可以决定你已经完成了大型数据结构(数组,对象),即使周围的范围/行为可以无限期地存在(通过闭包)在应用程序中.要允许GC拾取该数组并回收其内存,请使用取消设置引用someCoolNumbers = null.

如果你已经声明了const someCoolNumbers = [...];那么你将无法这样做,所以内存将保持使用,直到父范围(通过方法所cool具有的闭包)在cool未设置或自己GCd时消失.

更新

为了清楚地说明,因为这里的一些评论帖中存在很多混淆/争论,这是我的观点:

const绝对地,积极地,无可否认地对GC产生影响 - 特别是,值在较早时间手动GCd的能力.如果通过const声明引用该值,则无法取消设置该引用,这意味着您无法提前获取值GCd .当范围被拆除时,该值只能是GCd.

如果您希望能够手动为之前的GC设置一个值,而父作用域仍然存在,则您必须能够取消设置对该值的引用,如果您使用了该值,则不能这样做const.

有些人似乎相信我的说法const可以阻止任何GC.这不是我的主张.只是它阻止了早期的手动GC.

  • 底线 - 如果你想分配给变量,不要把它变成`const`.如果您不需要分配它并希望它受到保护,请将其设为const.没有比这更复杂的了.您只是定义了一个您可能实际想要分配给它的情况,所以在这种情况下不要使它成为`const`.我坚持认为,制作一些"const"并不会以任何方式改变它的垃圾收集.它确实会影响你是否可以分配它,所以如果你想为它分配一些东西以便摆脱你以前分配给它的东西,那么就不要把它变成`const`. (5认同)
  • 它会影响你手动释放对它的引用的能力 - 是的 - 你不能修改`const`变量.正如我已经说过大约5次.如果由于任何原因打算在将来更改变量的值,那么不要使用`const`.否则,这是一个很棒的功能.单独留下一个函数顶部的`const`变量和`var`变量将在完全相同的时间进行垃圾收集. (2认同)
  • @ jfriend00好悲伤,你仍然断言变量得到了GCd.它没有.**值**得到GCd.保存对这些值的引用的变量将阻止GC.如果无法更改这些引用,则可以提前阻止GC**如果您希望它**.我一遍又一遍地说的是,"const会影响GC,因为它会阻止你获得早期GC,如果你想要它,那么这个值比范围拆卸" (2认同)
  • @KyleSimpson:如果你想挑剔,变量*是用它们的范围收集的垃圾(或者早期取决于引擎优化).所以你必须说"*`const`会影响GC的值,因为它会阻止你删除引用,但它不会影响变量*的GC".你和你的朋友都在这里,现在就停止争论:-) (2认同)
  • @KyleSimpson感谢Kyle回复此事.我现在完全理解这个问题,但是当我读到这本书时,我真的没有.我通常不会很难理解你的写作 - 实际上恰恰相反 - 所以也许在下一版本/本书更新中值得扩展? (2认同)