問題描述
垃圾回收在 JavaScript 中是如何工作的?它類似于 .NET 垃圾收集嗎?是不是因為 VBScript 中垃圾回收的實現很糟糕,人們才避免使用它,而偏愛 JavaScript 作為他們的標準客戶端語言?
垃圾回收是如何工作的?
簡短的回答是:當一塊內存(比如一個對象)不再可訪問時,它就有資格被回收.何時、如何或是否回收完全取決于實現,不同的實現方式不同.但在語言層面,它是自動的.
例如:
函數 foo() {變量欄;酒吧 = 新的真正大規模對象();bar.someCall();}
當 foo
返回時,bar
指向的對象自動可用于垃圾回收,因為沒有任何東西可以引用它.
對比:
函數 foo() {變量欄;酒吧 = 新的真正大規模對象();bar.someCall();返回欄;}//其他地方var b = foo();
...現在對該對象的引用在調用中仍然存在,并且一直存在,直到/除非調用者將其他內容分配給 b
或 b
超出范圍.
同時對比:
函數 foo() {變量欄;酒吧 = 新的真正大規模對象();bar.someCall();設置超時(函數(){alert("三秒過去了");}, 3000);}
這里,即使在foo
返回后,定時器機制也有對定時器回調的引用,而定時器回調 —閉包 —對創建它的上下文有一個引用,該上下文又包含 bar
變量.因此,理論上,當 foo
返回時,bar
所指的內容不能立即用于垃圾回收.相反,它會一直保留到計時器觸發并釋放其對回調的引用,從而使回調及其引用的上下文符合 GC 條件.(在實踐中,現代 JavaScript 引擎可以并且確實優化了閉包.例如,在上面,靜態分析顯示回調不引用 bar
,并且不包含任何 eval
或 new Function
代碼可能會在運行時動態引用它,因此 JavaScript 引擎可以安全地將 bar
排除在函數引用的上下文之外,從而使它所指的東西有資格獲得 GC — 和現代的).(在這篇文章中了解更多關于閉包的信息.)p>
JavaScript 在清理循環引用時沒有問題,順便說一句,例如:
函數 foo() {變量 a, b;一個 = {};b = {};b.refa = a;a.refb = b;}
當 foo
返回時,a
指的是 b
并且反之亦然的事實不是問題.由于沒有其他內容涉及它們中的任何一個,因此它們都可以被清理.在 IE 上,如果其中一個對象是主機提供的對象(例如 DOM 元素或通過 new ActiveXObject
創建的東西)而不是 JavaScript 對象,則這不為真.(例如,如果您將 JavaScript 對象引用放在 DOM 元素上,并且 JavaScript 對象引用回 DOM 元素,即使沒有人引用它們中的任何一個,它們也會在內存中相互保存.)但這是一個 IE bug問題,不是 JavaScript 的問題.
回復:
<塊引用>是因為 vbscript GC 不好,人們將 javascript 作為他們的標準客戶端 api 嗎?
JavaScript 是原始客戶端網絡腳本語言.VBScript 只是在后來微軟推出瀏覽器時才出現,并且只在微軟瀏覽器中得到支持.如果您想使用最廣泛的瀏覽器,JavaScript 曾經是并且現在是唯一的客戶端腳本游戲.<subjective>它也是經典 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 中是如何工作的?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!