無奈的開頭
關於DOM節點操做,若是僅僅是根據標準API來操做,那是最簡單不過的了。可是現實中卻哪有這麼容易的問題讓咱們解決,其實不單單是節點的克隆與刪除,節點的添加也是如此,並且添加節點須要考慮的狀況更多,這裏不詳細講解,只說明大概過程。node
問題那麼多,主要出如今瀏覽器自身實現上,其中尤屬legacy IE上—IE6,7,8. 在添加節點的API實現上,IE作了一個貢獻,那就是insertAdjacentHTML函數被歸入HTML5規範上,這個函數在以前的文章中詳細講解並實現過,不提。此後,IE的行爲卻不值得提倡,由於咱們的兼容性主要針對的就是legacy IE。瀏覽器
克隆節點,規範的API是cloneNode(boolean),boolean爲true時進行深克隆。可是legacy IE卻有一個奇怪的bug,那就是經過該方法克隆的副本,卻仍含有相關的事件處理函數和用戶自定義屬性,並且修改刪除這些屬性或者函數,會影響到源節點的屬性
。。。着實讓人無語。解決方案另闢蹊徑,便可以經過獲取副本的HTML字符串,從新構造一個DOM節點,這樣根據字符串反系列化的副本就不會包含在js中額外操做的屬性或者事件處理程序。app
刪除節點理應沒有什麼問題,可是legacy IE下僅僅使用removeNode會出現內存泄露問題,被刪除的節點有部份內存並不會被回收,若是長時間運行該程序,則可能會出現內存耗盡的危險,只有關閉頁面纔可能回收這些內存。可是能夠利用outerHTML屬性作文章,他能夠更有效的刪除佔用的內存,可是須要注意的是這種方法仍然不會徹底釋放佔用的內存,可是整體回收的內存大於removeNode方法。函數
實現
/** * 舊版IE(IE678)拷貝元素節點,會連同事件處理函數和用戶自定義屬性一同拷貝給 * 副本,而且修改副本的事件處理函數和自定義屬性會影響到源節點。 */ clone = function(){ // 若是是IE678下的bug var el,c; if(Screen.support.cloneNodeWithHandler){ el = this[0].cloneNode(true); c = doc.createElement("div"); c.appendChild(el); return S.DomParser(c.innerHTML).firstChild; }else{ return this.cloneNode(true); } } remove = function(){ this.each(function(el){ if(el.nodeType && el.nodeType == 1){ S._unData(el); if(el.parentNode){ el.parentNode.removeChild(el); } // IE 678下這樣會形成內存泄露,元素節點刪除以後 // 仍有部份內存不能回收。可經過outerHTML回收,可是 // 須要知道的是這種方法也不能回收節點使用的所有內存,可是 // 最起碼回收的比removeChild多。 if(typeof el.outerHTML !== undefined){ el.outerHTML = ""; } } }); return this; }
上述代碼是本人私人庫實現的一部分,有錯誤之處還請指出。this