无奈的开头
关于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