2010-06-22 28 views
3

如果我有一個對象的兩個功能,下面的代碼:JQuery事件是否會在銷燬綁定的內容時自動解除綁定?

add: function() 
{ 
    // create trip. 
    var trip = new Trip(); 

    // add the trip using its id. 
    this.trips[trip.id] = trip; 
}, 

remove: function(tripId) 
{ 
    // remove trip. 
    delete this.trips[tripId]; 
} 

注:換行對象的構造結合了一堆定製JQuery的事件處理程序的本身。

Trip對象被刪除時,綁定到Trip對象的事件處理程序是否會自動銷燬/清除?

如果dom節點被移除並且綁定了事件處理程序,會發生同樣的情況嗎?

另外我讀了垃圾收集器沒有清理對象,直到對它們的所有引用都不存在爲止,綁定到對象的事件處理程序本身也被視爲引用並防止對象被清理,當我不再引用它?

+0

您可以粘貼自定義事件附加到Trip對象的構造函數部分嗎? – Anurag 2010-06-22 20:38:36

回答

5

的事件將不會如jQuery的刪除維護所有綁定的事件處理程序的中央存儲庫,並且不知道是否或何時您刪除相關的使用delete的對象。試試這個小測試來確認。 (jQuery的僅1.4.2)

jsfiddle link

// 1. a regular JS object 
var root = {}; 
// Since we can't delete anything created with var (except on Chrome), 
// we use an object property here. An array value works just as well, 
// which is already the case in your example. 
root.o = {}; 

// 2. at this point, jQuery creates an internal property 
// jQuery<UNIQ_ID>, for example jQuery1277242840125 inside object o 
$(root.o).bind("myEvent", function() { alert("here"); }); 

// 3. get the *internal* index jQuery assigned this object: 
// there's only 1 property, so we just enumerate and fetch it. 
var internalIndex; 
for(var prop in root.o) { 
    internalIndex = root.o[prop]; 
} 

// 4. delete the object 
delete root.o; 

// 5. query jQuery internal cache with the internal index from step 3 
console.log(jQuery.cache[internalIndex].events); 
​ 

步驟5應記錄上與前鄰對象相關聯的所有事件類型,包括「myEvent」的陣列,和它的相關聯的處理程序中,所以沒有綁定事件處理程序不會自動刪除。這是我看到記錄到日誌中(去掉了不相關的屬性):

▾ Object 
    ▾ myEvent: Array (1) 
    ▾ 0: Object 
     ▸ handler: function() { alert("here"); } 
     namespace: "" 
     type: "myEvent" 
     length: 1 

對象刪除,但是,不影響,因爲預計將被刪除。然而,由於jQuery緩存中的數據會保留在那裏,因此這種情況在牆上會出現漏洞。

看來,儘管您可以將事件綁定到純JavaScript對象,但您無法解除綁定它們。這似乎jQuery的假設解除綁定,當對象是DOM節點,並引發以下錯誤:

Uncaught TypeError: Object #<an Object> has no method 'removeEventListener' 

即使是對能夠將事件綁定到對象上,我相信,無證一部分。所以,你必須要對這個有點小心,因爲試圖清理該對象的事件處理程序引用時以下將不起作用:

$(object).remove() 
$(object).unbind(..) 

作爲一種變通方法,清理跳閘對象時,可以明確地呼叫removeData來完成這項工作。

$(object).removeData(); 

正如我已經提到的,它越來越沒膝深的使用jQuery的內部,所以你可能想看看一個替代的解決方案,或者提防庫升級,可以很容易地破壞你的代碼,這是不是很不太可能。

+0

['$(object).removeData();'](http://api.jquery.com/removeData)是解決方案。這將刪除存儲在該對象的jQuery數據緩存(其中包括事件句柄)中的所有數據。 – gnarf 2010-06-22 22:51:41

+0

謝謝,我會在早上測試這個,如果它有效,我會批准它。你所說的關於JQuery維護事件的中央存儲庫關係到我,因爲這意味着它可能不會被刪除。請參閱以下關於刪除對象:http://stackoverflow.com/questions/742623/deleting-objects-in-javascript如果任何引用仍然是一個對象,它似乎垃圾收集器不會清理它,因此,如果JQuery存儲有關事件的信息以及它綁定的內容,它可能引用了對象和塊集合? – Gavin 2010-06-23 00:51:39

+0

鑑於上述我認爲internalIndex也可能阻塞集合,因爲它引用了對象的屬性?通過螢火蟲手動檢查$ .cache可能會更安全。 – Gavin 2010-06-23 01:02:24

0

據我所知,只能將事件處理程序綁定到節點,或者在特殊情況下,窗口,文檔等。對於DOM節點,事件處理程序將被刪除。即使他們不是,他們也無法被觸發。刪除對象將刪除與之關聯的事件處理程序。事件處理程序不應阻止垃圾收集對象。

0

Would the same occur for a dom node if it was removed and had event handlers bound to it?

this.handlerClick = function() { ... }; 

$(this.testDomNode).bind('click', this.handlerClick); 

this.testDomNode.parentNode.removeChild(this.testDomNode); 

使用上面的代碼,並在火狐FireQuery測試去除DOM節點不解除綁定該事件的處理程序,

好像你必須明確地解除綁定處理程序移除DOM之前節點如下:

$(this.testDomNode).unbind('click', this.handlerClick); 

this.testDomNode.parentNode.removeChild(this.testDomNode); 
相關問題