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
变量或它指向的不是任何不同的内容var
或let
变量.当它超出范围并且不再可访问时,其内容将有资格进行垃圾回收.
const
有许多优点.它允许开发人员声明一些意图,即此变量指向的内容不会被代码更改,并且可能允许运行时进行一些优化,因为它知道变量的内容无法更改.并且,它可以防止恶意或意外代码不断更改该变量的内容.在适当的情况下使用时,这些都是好事.一般来说,你应该const
尽可能多地使用.
不,没有性能影响.本文指的是通过"取消设置"变量来帮助垃圾收集器(很少需要)的做法:
{
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
.
变量的生命周期(当它超出范围时)不受此影响.但是如果垃圾收集器搞砸了,常量将始终保持初始化的值,并防止垃圾收集,而普通变量可能不再容纳垃圾收集器.
垃圾收集器(GC)工作的方式是什么东西被什么都引用("无法到达")时,GC可以安全地说不再使用某些东西并回收那些东西所使用的内存.
能够替换变量的值允许删除对值的引用.但是,不像var
,const
不能重新分配一个值.因此,无法从引用该值中删除该常量.
当常量变为"超出范围"时,可以回收常量,如变量,就像函数退出时一样,并且内部的任何内容都不会形成闭包.
我的书中的那个注释指的是这样的情况,你希望能够在其父范围的生命周期结束之前手动创建值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.