JavaScript中的垃圾收集是如何工作的?

JavaScript中的垃圾收集是如何工作的?,javascript,vbscript,garbage-collection,Javascript,Vbscript,Garbage Collection,JavaScript中的垃圾收集是如何工作的?它类似于.NET垃圾收集吗?是不是因为VBScript中垃圾收集的实现很糟糕,所以人们避免了它,并将JavaScript作为标准客户端语言 垃圾收集是如何工作的 简单的回答是:当一块内存(比如一个对象)不再可访问时,它就有资格被回收。何时、如何或是否回收完全取决于实现,不同的实现做得不同。但在语言层面上,它是自动的 例如: function foo() { var bar; bar = new ReallyMassiveObject

JavaScript中的垃圾收集是如何工作的?它类似于.NET垃圾收集吗?是不是因为VBScript中垃圾收集的实现很糟糕,所以人们避免了它,并将JavaScript作为标准客户端语言

垃圾收集是如何工作的

简单的回答是:当一块内存(比如一个对象)不再可访问时,它就有资格被回收。何时、如何或是否回收完全取决于实现,不同的实现做得不同。但在语言层面上,它是自动的

例如:

function foo() {
    var bar;

    bar = new ReallyMassiveObject();
    bar.someCall();
}
foo
返回时,指向的对象
bar
自动可用于垃圾收集,因为没有任何对象剩下了对它的引用

与之相比:

function foo() {
    var bar;

    bar = new ReallyMassiveObject();
    bar.someCall();
    return bar;
}
// elsewhere
var b = foo();
function foo() {
    var bar;

    bar = new ReallyMassiveObject();
    bar.someCall();
    setTimeout(function() {
        alert("Three seconds have passed");
    }, 3000);
}
…现在,对对象的引用在调用后仍然存在,并一直存在,直到/除非调用方将其他内容分配给
b
b
超出范围

与之形成对比的还有:

function foo() {
    var bar;

    bar = new ReallyMassiveObject();
    bar.someCall();
    return bar;
}
// elsewhere
var b = foo();
function foo() {
    var bar;

    bar = new ReallyMassiveObject();
    bar.someCall();
    setTimeout(function() {
        alert("Three seconds have passed");
    }, 3000);
}
在这里,即使在
foo
返回之后,计时器机制也有一个对计时器回调的引用,而计时器回调(一个闭包)有一个对创建它的上下文的引用,该上下文又包含
bar
变量。因此,理论上,当
foo
返回时,
bar
所指的内容不能立即用于垃圾收集。相反,它会一直保留,直到计时器触发并释放对回调的引用,从而使回调及其引用的上下文符合GC的条件。(在实践中,现代JavaScript引擎可以并且确实可以尽可能优化闭包。例如,在上面的静态分析中,回调不引用
bar
,也不包含任何
eval
new Function
代码,这些代码可能在运行时动态引用它,因此JavaScript引擎可以安全地离开<代码>条形图与函数所指的上下文无关,因此使它所指的内容符合GC的条件(而现代函数也适用)。(有关中闭包的详细信息。)

JavaScript在清理循环引用方面没有问题,顺便说一句,例如:

function foo() {
    var a, b;

    a = {};
    b = {};
    b.refa = a;
    a.refb = b;
}
foo
返回时,
a
指的是
b
,反之亦然,这不是问题。因为没有其他任何东西涉及到它们,所以它们都可以被清理干净。在IE上,如果其中一个对象是主机提供的对象(例如DOM元素或通过
新建ActiveXObject
创建的对象),而不是JavaScript对象,则这是而不是。(例如,如果您将JavaScript对象引用放在DOM元素上,并且JavaScript对象引用回DOM元素,那么即使没有人引用它们,它们也会在内存中相互保留。)但这是一个IE错误,不是JavaScript问题

关于:

是不是因为vbscript GC不好,人们才恢复使用javascript作为标准客户端api

JavaScript是原始的客户端web脚本语言。VBScript只是在微软推出浏览器之后才出现,而且只有微软浏览器才支持VBScript。如果你想使用最广泛的浏览器,JavaScript过去是,现在也是唯一的客户端脚本游戏。这也是语言经典VBScript的八倍左右

原则上,在所有语言中都使用类似的方法。但是,它们的实现在不同的环境中会有所不同(例如,每个浏览器使用不同的方式实现JavaScript GC)。有关Chrome GC的简要概述,请参见例如


至于VBScript,它是作为JavaScript的竞争对手/替代语言创建的,只在IE中运行。在引入VBS时,这是一个相当合理的决定——IE拥有90%以上的浏览器份额,看起来VBS可以替代(当时广泛支持、较旧且功能较差的)JavaScript;现在不多了。另外,VBScript基本上是VisualBasic Lite,带有该品牌的所有负面含义。

简单的回答是:它取决于平台。每个浏览器或JS虚拟机都可以按照他们想要的方式自由地实现它。“但这是一个很好的解释。”海勒姆:的确——嗯,在一定范围内。平台不能以违反JavaScript范围规则的方式回收内容。而一个从不回收任何东西的平台很可能是不成功的。@T.J.克劳德:是的,但他们显然有自己的优化技巧和不同的引用计数方法,例如。@haylem:对。“何时、如何或是否回收完全取决于实施……”@T.J.Crowder true,我错误地将中描述的情况联系起来,thxVBS于1996年引入IE。当时,网景拥有大约90%的浏览器份额。VBS为MS提供了连接本机系统组件的方法,这在当时都是关于锁定的。另请参阅