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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4324133/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 11:01:30  来源:igfitidea点击:

How does garbage collection work in JavaScript?

javascriptvbscriptgarbage-collection

提问by Ali Tarhini

How does garbage collection work in JavaScript? Is it similar to .NET garbage collection? And is it because the implementation of garbage collection in VBScript is bad that people avoided it and established a preference for JavaScript as their standard client-side language?

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

回答by T.J. Crowder

How does garbage collection work?

垃圾收集是如何工作的?

The short answer is: When a block of memory (an object, say) is no longer reachable, it is eligible to be reclaimed. When, how, or whether it is reclaimed is entirely up to the implementation, and different implementations do it differently. But at a language level, it's automatic.

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

For example:

例如:

function foo() {
    var bar;

    bar = new ReallyMassiveObject();
    bar.someCall();
}

When fooreturns, the object barpoints to is automatically available for garbage collection because there is nothing left that has a reference to it.

foo返回时,bar指向的对象自动可用于垃圾收集,因为没有任何东西可以引用它。

Contrast with:

对比:

function foo() {
    var bar;

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

...now a reference to the object survives the call, and persists until/unless the caller assigns something else to bor bgoes out of scope.

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

Also contrast with:

也对比:

function foo() {
    var bar;

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

Here, even after fooreturns, the timer mechanism has a reference to the timer callback, and the timer callback — a closure — has a reference to the context where it was created, which in turn contains the barvariable. As a result, in theory, what barrefers to isn't available for garbage collection immediately when fooreturns. Instead, it's kept around until the timer fires and releases its reference to the callback, making the callback and the context it refers to eligible for GC. (In practice, modern JavaScript engines can and do optimize closures where they can. For instance, in the above, static analysis shows the callback doesn't refer to bar, and doesn't contain any evalor new Functioncode that might refer to it dynamically at runtime, so the JavaScript engine can safely leave barout of the context the function refers to, thus making what it refers to eligible for GC — and modern ones do). (More about closures in this article.)

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

JavaScript has no problem handling cleaning up circular references, btw, so for instance:

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

function foo() {
    var a, b;

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

When fooreturns, the fact that ais referring to band vice-versa isn't a problem. Since nothing else refers to either of them, they can both get cleaned up. On IE, this is nottrue if one of the objects is a host-provided object (such as a DOM element or something created via new ActiveXObject) instead of a JavaScript object. (So for instance, if you put a JavaScript object reference on a DOM element and the JavaScript object refers back to the DOM element, they keep each other in memory even when no one is referencing either of them.) But that's an IE bugissue, not a JavaScript thing.

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

Re:

回覆:

is it because the vbscript GC is bad that people reverted to javascript as their standard client side api?

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

JavaScript was the originalclient-side web scripting language. VBScript only came later, when Microsoft came out with a browser, and was only ever supported in Microsoft browsers. JavaScript was and is the only client-side scripting game in town if you want to work with the broadest range of browsers. <subjective>It's also about eight times the language classic VBScript ever was. ;-) </subjective>

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

回答by Piskvor left the building

Garbage collection, in principle, uses similar methods in all languages. Their implementation will however be different in different environments (e.g. each browser uses a different way of implementing JavaScript GC). For a very brief overview of Chrome's GC, see e.g. this.

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

As for VBScript, it was created as a JavaScript rival/replacement language that only runs in IE. This was a fairly reasonable decision at the time VBS was introduced - IE had 90+% of the browser share and it looked that VBS can replace the (widely supported, older and feature-poor at the time) JavaScript; not so much nowadays. Also, VBScript is basically Visual Basic Lite, with all the negative connotations to go with that brand.

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