1

简单的问题,什么对垃圾收集器更好:

  • 将对象添加到数组并将 null 分配给数组单元格

this.requests[i] = new NiceClass();

this.requests[i] = null;

  • 创建简单变量并将 null 分配给该变量

var niceClass = new NiceClass();

niceClass = null;

我问是因为我想避免使用数组,因为在创建大量对象期间 - 尽管破坏了对对象的引用,所以垃圾收集器能够抓取不必要的对象 - 数组正在增长,所以我很好奇,这里有必要还是只使用变量会更好吗?

4

1 回答 1

2

你忘记了几件事:

JS 的 GC 工作方式取决于实现:V8 对内存的管理非常好,而旧版本的 IE 泄漏的不仅仅是生锈的滤锅。
将变量设置为 null,但不会对其进行初始化Null不像null其他语言(只需尝试typeof null在控制台中输入)。试试someVar = undefined吧。即便如此,Js 确实有一个保留delete关键字,在我看来,这就是你所追求的。
总而言之:如果对象被一个变量或一个数组引用:这并不重要:数组是稀疏的,所以如果你使用delete someArray[i];,那 or 之间真的不应该有任何区别delete someVar;
注意:删除全局范围内的变量总是返回 true,但如果该变量被显式声明(使用var关键字)或者如果它是一个函数,它将不会被删除。只能删除隐含的全局变量,因此:

var global1 = 'I cannot be deleted';
function global2()
{
    global3 = 123;//implied global
}
global4 = function()
{
    console.log('implied global function, can be deleted');
};
delete global1;//returns true
console.log(global1);//I cannot be deleted
delete global2;
global2();//shouldn't create global3, because it was deleted but:
console.log(global3);//123
delete global3;//true
console.log(global3);//undefined, was deleted
delete global4;//true
global4();//error <--- was deleted = reference error

但是:在这两种情况下,取消引用仍然在某个闭包中或脚本中某处的另一个变量中引用的任何对象都不会 GC it
一般来说,JS GC 只是循环标记和刷内存:当对任何给定对象的所有引用超出范围时,它们被标记并释放内存。您对此过程没有任何真正的控制权,因此您无法真正为此优化代码。

即便如此,如果您仍然想继续,并在 FF 或 Chrome 中使用时间线和分析器工具,那么请成为我的客人。但请记住:当您这样做时,您正在针对特定的 JS 引擎进行优化:V8 优化的代码可能会在 Chrome 和 Safari 中生成更清洁的内存,但就您所知,IE 可能会产生完整的哈希,或者您使用的一些技巧会导致 FF 变慢,这比一个相当大的数组首先要做的要多。
我想我会在这里停止这种咆哮......底线:你无法优化你无法真正控制的东西。

更新:

由于我刚刚阅读了您对您当前遇到的内存泄漏的评论:我认为将变量设置为nullundefineddelete至不会对您有多大好处。确保(现代)GC 能够完成其工作的一个更好的方法是巧妙地使用闭包:每当函数返回时,在其范围内声明的变量都会被标记为 GC。如果返回了这些变量,或者该函数的返回值是引用这些变量的对象或另一个函数,则它们不会被 GC'ed,但不再引用的那些变量将被释放。
全局变量永远不会超出范围,因此永远不会被 GC'ed。这就是为什么全球人是邪恶的. 如果你真的有很多 JS 代码需要优化:开始把东西放在 IIFE 中,这可以产生巨大的差异,而且只需很少的努力。

于 2012-10-28T16:50:49.470 回答