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

问题描述 投票:0回答:2

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

javascript vbscript garbage-collection
2个回答
81
投票

垃圾收集是如何工作的?

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

例如:

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

...现在,对该对象的引用在调用中保留下来,并持续存在,直到/除非调用者将其他内容分配给

b
b
超出范围。

同时对比:

function foo() {
    var bar;

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

在这里,即使在

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

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

function foo() {
    var a, b;

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

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

回复:

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

JavaScript 是原始客户端 Web 脚本语言。 VBScript 后来才出现,当 Microsoft 推出浏览器时,并且仅在 Microsoft 浏览器中受支持。如果您想使用最广泛的浏览器,JavaScript 过去是、现在仍然是唯一的客户端脚本游戏。 它的性能大约是经典 VBScript 语言的八倍。 ;-)


2
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.