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

IT技术 javascript vbscript garbage-collection
2021-02-09 10:29:20

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

2个回答

垃圾收集是如何工作的?

简短的回答是:当一块内存(比如一个对象)不再可达时,它就有资格被回收。何时、如何或是否回收完全取决于实现,不同的实现以不同的方式进行。但在语言层面,它是自动的。

例如:

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();

...现在对对象的引用在调用中幸存下来,并持续到/除非调用者分配其他内容bb超出范围。

也对比:

function foo() {
    var bar;

    bar = new ReallyMassiveObject();
    bar.someCall();
    setTimeout(function() {
        alert("Three seconds have passed");
    }, 3000);
}

在这里,即使在foo返回之后,定时器机制也有一个对定时器回调的引用,而定时器回调——一个闭包 ——有一个对它被创建的上下文的引用,而上下文又包含bar变量。因此,理论上,返回bar时不能立即进行垃圾回收foo相反,它会一直保留到计时器触发并释放对回调的引用,从而使回调及其引用的上下文符合 GC 条件。(在实践中,现代 JavaScript 引擎可以并且确实会尽可能优化闭包。例如,在上面,静态分析显示回调不引用bar,并且不包含任何evalnew Function可能在运行时动态引用它的代码,因此 JavaScript 引擎可以安全地将bar函数引用的上下文排除在外,从而使其引用的内容符合 GC 的条件——现代的也这样做)。(更多关于本文中的闭包。)

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

function foo() {
    var a, b;

    a = {};
    b = {};
    b.refa = a;
    a.refb = b;
}

foo返回时,a所指的事实b和反之亦然不是问题。由于没有其他内容涉及它们中的任何一个,因此它们都可以得到清理。在 IE 上,如果其中一个对象是主机提供的对象(例如 DOM 元素或通过 创建的内容)而不是 JavaScript 对象,则情况并非如此new ActiveXObject(例如,如果您将 JavaScript 对象引用放在 DOM 元素上,并且 JavaScript 对象引用回 DOM 元素,即使没有人引用它们中的任何一个,它们也会将彼此保留在内存中。)但这是一个 IE错误问题,不是 JavaScript 的东西。

回覆:

是不是因为 vbscript GC 不好,人们恢复到 javascript 作为他们的标准客户端 api?

JavaScript 是最初的客户端 Web 脚本语言。VBScript 是在微软推出浏览器之后才出现的,并且只在微软浏览器中得到支持。如果您想使用最广泛的浏览器,JavaScript 曾经并且现在是城里唯一的客户端脚本游戏。<subjective>它也是经典 VBScript 语言的八倍。;-) </主观>

@haylem:对。“何时、如何或是否回收完全取决于实施......”
2021-03-26 10:29:20
@TJ Crowder:是的,但例如,他们显然可以拥有自己的优化技巧和不同的引用计数方法。
2021-03-29 10:29:20
简短的回答是:这取决于平台。每个浏览器或 JS VM 都可以按照他们想要的方式自由地实现它。但很好的解释。
2021-03-31 10:29:20
@TJCrowder 是的,我错误地关联了informit.com/articles/article.aspx?p=26993 中描述的情况,谢谢
2021-04-03 10:29:20
@haylem:确实——嗯,在限制范围内。平台不能以违反 JavaScript 范围规则的方式回收东西。一个从不回收任何东西的平台很可能不会成功。
2021-04-04 10:29:20

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

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

VBS 于 1996 年随 IE 一起推出。当时,Netscape拥有大约 90% 的浏览器份额。VBS 为 MS 提供了与本地系统组件相关联的方法,这在当时完全是关于锁定的。
2021-04-03 10:29:20