垃圾收集如何在JavaScript中工作? [英] How does garbage collection work in JavaScript?
问题描述
垃圾收集在JavaScript中如何工作?它与.NET垃圾收集类似吗?这是因为在VBScript中垃圾回收的实现是不好的,人们避免它,并建立了JavaScript作为他们的标准客户端语言的偏好?
简单的答案是:当一个块的内存(一个对象,说)不再可及,它有资格被回收。何时,如何或是否回收完全取决于实施,而不同的实施方式则以不同的方式进行。但在语言层面上,这是自动的。
例如:
function foo(){
var bar;
bar = new ReallyMassiveObject();
bar.someCall();
当 foo
返回,$ bar
指向的对象自动可用于垃圾回收,因为没有任何内容可以引用它。
<对比:
function foo(){
var bar;
bar = new ReallyMassiveObject();
bar.someCall();
返回栏;
}
//别处
var b = foo();
...现在对对象的引用仍然存在,直到/除非调用者指定 b
或 b
的其他内容超出了范围。
<与之相反:
function foo(){
var bar;
bar = new ReallyMassiveObject();
bar.someCall();
setTimeout(function(){
alert(Three seconds have passed);
},3000);
}
在这里,即使在 foo
返回,定时器机制有一个对定时器回调的引用,并且定时器回调 — 闭包 —有一个对创建它的上下文的引用,它又包含 bar
变量。因此,理论上,当 foo
返回时, bar
指向的垃圾收集不可立即使用。相反,它会一直存在,直到计时器触发并释放其对回调的引用,使回调以及它引用的符合GC的上下文。 (实际上,现代JavaScript引擎可以并且可以优化闭包,例如,在上面的例子中,静态分析显示回调没有引用 bar
,并且doesn不包含可能在运行时动态引用它的任何 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对象。 (例如,如果您将JavaScript对象引用放在DOM元素上,而JavaScript对象引用DOM元素,即使没有人引用它们中的任何一个,它们也会将内存保留在内存中。)但是,这是一个IE bug 问题,不是JavaScript的事情。
Re:
< blockquote>
这是因为vbscript GC很糟糕,人们将其转换为标准的客户端api作为javascript?
< JavaScript是原创的客户端网页脚本语言。 VBScript仅在后来才出现,当时微软推出了浏览器,并且只有微软浏览器才支持。如果你想使用最广泛的浏览器,JavaScript是并且是唯一的客户端脚本游戏。 <主观>它也是VBScript历史上的八倍。 ;-)< /主观>
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?
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 foo
returns, the object bar
points to is automatically available for garbage collection because there is nothing left that has a reference to it.
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 b
or b
goes out of scope.
Also contrast with:
function foo() {
var bar;
bar = new ReallyMassiveObject();
bar.someCall();
setTimeout(function() {
alert("Three seconds have passed");
}, 3000);
}
Here, even after foo
returns, 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 bar
variable. As a result, in theory, what bar
refers to isn't available for garbage collection immediately when foo
returns. 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 eval
or new Function
code that might refer to it dynamically at runtime, so the JavaScript engine can safely leave bar
out 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.)
JavaScript has no problem handling cleaning up circular references, btw, so for instance:
function foo() {
var a, b;
a = {};
b = {};
b.refa = a;
a.refb = b;
}
When foo
returns, the fact that a
is referring to b
and vice-versa isn't a problem. Since nothing else refers to either of them, they can both get cleaned up. On IE, this is not true 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.
Re:
is it because the vbscript GC is bad that people reverted to javascript as their standard client side api?
JavaScript was the original client-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中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!