当我清空一个数组时,其中的javascript对象从内存中删除吗?

3

我从来没有太关注垃圾回收问题,也不知道在制作小型JavaScript游戏/应用时是否需要考虑这个问题。任何建议都将不胜感激,但我最后还有一个具体问题需要问。

我经常编写以下形式的代码:

var foos=new Array();
generateFoos();
function generateFoos()
{
    foos=[];
    for (fooIndex=0;fooIndex<numberOfFoos;fooIndex++)
    {
        foos[fooIndex]=new foo(Math.random(),Math.random());
    }
} 
function foo(bar,bas)
{
   this.bar=bar;
   this.bas=bas;
}

当我执行foos=[](第5行)时,这会删除数组中的对象吗?还是它们会浮动在某个地方,使程序变得更大和更慢?如果我想要多次调用generateFoos(),例如每次用户按下一个键时调用该函数,应该怎么做呢?
谢谢!

foos[] 仅存在于函数的作用域中 - 因此,如果函数代码结束,则 foos 将被删除。 - Bernhard
1
@Bernhard 不,foos在第一行就被声明了。 - Lee Taylor
为什么要使用 delete 而不是仅清空数组? - Nick Manning
@LeeTaylor 噢,那么它将一直存在,直到您删除该变量 - 因此在那段时间内它将在内存中。 - Bernhard
@NickManning delete会完全删除变量的引用。清空数组只会将数组清空。 - Bernhard
1
不,你不应该使用 delete 来做这件事。Delete 只会从对象中移除一个属性,它并不能“删除”一个变量。请先了解一下 delete 的工作原理。 - Geuis
2个回答

7
针对一个具体的问题,因为被接受的答案实际上没有直接回答问题,是的,foo=[]确实会取消引用数组中之前的任何值。 正如Ales所说,“当对象变得不可达时,它就变得有资格进行垃圾回收。”确实,这是浏览器将从内存中清除此类内容的时间。 重要的一点是,delete不能进行垃圾回收。 你会在这个问题的评论区看到这一点。delete关键字从一个对象中删除属性,与垃圾回收无关。
我还想提供一些关于你代码本身的建议。
1)对于基本数据类型,请使用文字而不是new。
2)不要在声明函数之前调用函数。是的,它可以工作,但很混乱,以后很难阅读。记住,你花费的时间读取代码比编写代码多得多。让它容易跟随。
3)记住你的函数范围。任何未经var声明的变量都是全局的。使用var,它仍然在包含它的函数的范围内。另一种变量在函数中作用域的方法是将它们作为命名参数传递。
4)创建函数时请使用var。在你的代码中,你的函数是全局的。
5)使用空格。文本密度不是神圣的。你现在可能是20多岁,视力很好,但你很快就会欣赏到空白的空间。
6)在for循环中使用var声明计数器。除非你希望它们是全局的。而你几乎永远不会这样做。
现在让我们重新编写你的代码:
var numberOfFoos = 10,
    foos = [];

var generateFoos = function(){

    foos = [];

    for( var fooIndex = 0; fooIndex < numberOfFoos; fooIndex++ ){

        foos[ fooIndex ] = new foo( Math.random(), Math.random() );

    }

},

foo = function( bar, bas ){

   this.bar = bar;
   this.bas = bas;

}

generateFoos();
console.log( foos );

谢谢...非常有帮助的内容,我一定会采纳你的所有建议。对不起,Ales,因为我更改了采纳的答案。 - Nick Manning
我想指出,“4)在创建函数时,在函数上使用var。在您的代码中,您的函数是全局的。”是不正确的。在这种情况下使用var仅仅是风格上的区别,两个版本都会产生一个全局函数。如果没有封装函数,OP和你的版本是相同的(除了可能的函数提升)。即使OP的函数被封装了,通过函数声明而不是var声明也不会在作用域上有任何区别。 - James Bruckner

5
回答你的问题:当一个对象变得不可达时,它就可以进行垃圾回收。如果您的程序没有保留对该数组中其他对象的引用,它们将被垃圾回收。
实际的垃圾回收时间取决于许多方面和所选择的垃圾回收算法,但编写代码时不必担心这些。
在考虑垃圾回收时,最好的建议是让垃圾收集器完成其工作。不要试图指示或帮助它(例如通过手动将引用设置为空)。专注于代码的问题和功能方面。

谢谢...很高兴知道如果一个对象变得不可访问,它将被垃圾回收。这意味着在我给出的例子中,我不必担心存储成千上万个对象。 - Nick Manning
2
仍然保持对内存的关注是一个好主意。例如,在Javascript应用程序中,内存泄漏的主要来源之一是将处理程序绑定到全局事件,即使它们不再需要,也从未删除它们。 - robbrit
我同意。我不是JavaScript专家,但通常仍需要小心处理内存泄漏,不应通过将引用置空或显式调用GC来尝试提高GC性能。当代码完成并运行时,可以稍后进行GC调优。 - Aleš

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接