[英]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();
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
返回之后,定時器機制也有一個對定時器回調的引用,而定時器回調——一個閉包——有一個對它被創建的上下文的引用,而上下文又包含bar
變量。 因此,理論上,當foo
返回時, bar
所指的內容不能立即用於垃圾收集。 相反,它會一直保留到計時器觸發並釋放其對回調的引用,從而使回調及其引用的上下文符合 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 對象,則情況並非如此。 (例如,如果您將 JavaScript 對象引用放在 DOM 元素上,並且 JavaScript 對象引用回 DOM 元素,即使沒有人引用它們中的任何一個,它們也會將彼此保留在內存中。)但這是一個 IE錯誤問題,不是 JavaScript 的東西。
關於:
是不是因為 vbscript GC 不好,人們恢復到 javascript 作為他們的標准客戶端 api?
JavaScript 是最初的客戶端 Web 腳本語言。 VBScript 是在微軟推出瀏覽器之后才出現的,並且只在微軟瀏覽器中得到支持。 如果您想使用最廣泛的瀏覽器,JavaScript 曾經並且現在是鎮上唯一的客戶端腳本游戲。 <subjective>它也是經典 VBScript 語言的八倍左右。 ;-) </主觀>
垃圾收集原則上在所有語言中都使用類似的方法。 然而,它們的實現在不同的環境中會有所不同(例如,每個瀏覽器使用不同的方式來實現 JavaScript GC)。 有關 Chrome GC 的非常簡要的概述,請參見例如這個。
至於 VBScript,它是作為 JavaScript 競爭對手/替代語言創建的,只能在 IE 中運行。 在引入 VBS 時,這是一個相當合理的決定——IE 擁有 90+% 的瀏覽器份額,而且看起來 VBS 可以取代(當時廣泛支持的、舊的和功能不佳的)JavaScript; 現在沒有那么多了。 此外,VBScript 基本上是 Visual Basic Lite,帶有該品牌的所有負面含義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.