2013-06-28 43 views
4

如果我執行以下操作(在全球範圍內):Javascript:沒有名字的對象會發生什麼?

var myObject = {name: "Bob"}; 

我有辦法來指向在存儲器中的對象(即,字符串標識符「myObject的)」。我可以打開控制檯,輸入:myObject.name,控制檯將響應:

"Bob" 

現在,如果我只需要輸入:

{name: "Jane"}; 

我創建該對象的地方,我猜它繼續生活在一定的範圍內。有什麼方法可以找到它嗎?在某些通用商店的某個地方是否存在window

編輯:有人說它只會收集垃圾。

因此,如何這個例子:

var MyObject = function(){ 
    $("button").click(this.alert); 
} 

MyObject.prototype.alert = function(){ 
    alert("I heard that!") 
} 

new MyObject(); 

它不能被垃圾收集,因爲其回調綁定到DOM事件。生成的對象在哪裏存在並且可以訪問?

+0

都能跟得上。該對象被創建並收集垃圾。就像那些「使用嚴格」的字符串一樣。我的一些JS引擎甚至可能避免創建 – MaxArt

+0

其他人質疑,但刪除了他們的評論。你的第一個例子是甚至定義了你認爲的對象,還是僅僅是一個塊,一個標籤和一個字符串? –

+1

我已經更新了我的答案,在您的更新中擴展了一點(關於在構造函數中綁定事件處理程序,我可以補充說,這通常不是最好的主意( –

回答

2

簡短的回答是沒有,該對象不會在內存中的某處無法存活。比特生活是活的:如果你掌握了基本知識,那麼事實就複雜一點,但不是太多。

更新:
爲了響應您的更新:您的方式是正確的。回調是對MyObject.prototype.alert的引用,您可以使用this.alert訪問該引用,但該函數對象正在被構造函數原型引用,並且無論如何都不能被GC'ed。 實例本身並不涉及alert函數本身,因此它可以安全地進行GC操作。

把它看成是這樣的:

MyConstructor.prototype.alert = 0x000123;//some memory address 
    || 
    \/ 
0x00= [object Function]; 

函數對象本身不直接連接到任何東西,它漂浮有在內存中,並正在由原型引用。當你創建一個實例:

new MyConstructor().alert; 

解析如下:

[new MyConstructor instance] allocated at e.g 0x000321 
    || 
    \\ 
    \=>[alert] check for alert @instance -> not found 
      \\ 
      \=> check prototype, yield 0x00<-- memory address, return this value 

所以在執行該語句:

$("button").click(this.alert); 

this.alert是被解析爲0x000123的表達式。換句話說,jQ的click方法(函數對象)只接收alert函數對象的內存地址。這個實例,或者實際上構造函數完全不涉及。這就是爲什麼this或調用上下文可以根據調用函數的方式和位置而改變的原因。 see here for more on ad-hoc context determination

我連你一個更好的:

/*assume your code is here*/ 
new MyConstructor().alert = function(){ alert('I am deaf');}; 
MyConstructor.prototype.alert = 'foo'; 
$('#button').click(); 

你猜怎麼着,單擊事件警報「聽說」都是一樣的,在原型甚至沒有參與,讓僅此一例。
如果MyConstructor超出範圍,則click事件仍可正常工作,因爲GC仍然會看到尚未超出範圍的警報函數對象的引用。一切都可用於GC'ing,雖然...


JS垃圾收集器(GC)是一個標誌和滑動GC。當JS引擎遇到你的聲明時,它確實分配存儲你的對象所需的內存。當達到下一條語句時,該對象可能仍然在內存中。
GC不時檢查它在內存中看到的所有對象,並嘗試查找對該對象仍然可訪問的所有引用。當它遇到剛剛在該語句中創建的對象字面值時,但未分配引用時,該對象將被標記爲垃圾回收。
GC下次獲取滑動標記對象的業務時,該對象將從內存中移除。

當然,這對於所有發動機並不完全正確。假設你的聲明寫在IIFE,即返回功能:

var foo = function() 
{ 
    {name: 'bar'}; 
    return function() 
    { 
     return 'foobar'; 
    }; 
}()); 

有些發動機只保留在內存中IIFE的整個範圍,只有解除分配內存,以便示波器在返回值的 IIFE超出範圍(被標記爲GC)。其他引擎,比如我上次檢查的V8,實際上會標記外部範圍的那些沒有被返回值引用的對象/變量。
雖然可以想一想,但它可能不適用於這種情況,因爲即使在IIFE迴歸之前,GC甚至可能會開始......但總的來說,這只是挑剔。

還有的邏輯問題Or的考慮:

var name = (mayNotExist || {name:'default'}).name; 

在這種情況下,如果mayNotExist確實存在,對象字面甚至不會被創建,由於表情JS的短路評價。

一對夫婦對此事鏈接:

+0

感謝您的非常完整的答案。 –

5

如果沒有引用指向此對象(即,您沒有將它分配給任何變量或任何屬性的值),那麼就沒有辦法訪問它,事實上它並不像垃圾回收器可以立即回收這個內存。

+2

我喜歡認爲它已經逃脫並且生活在羔羊 – Yatrix

+2

@Yatrix我認爲這是'在林中',但'生活在羊羔'聽起來更美味! –

+0

@MattHarrison呵呵。我從來沒有上過林,但如果我曾經,我希望我有羊羔帶着我 – Yatrix

相關問題