我正在尝试找出在浏览器中深度克隆DOM树的最高效方法.
如果我开始
var div = document.getElementById("source"); var markup = div.innerHTML;
什么会更快,
var target = div.cloneNode(true);
要么
var target = document.cloneNode(false); target.innerHTML = markup;
我知道浏览器平台可能会在这里产生很大的不同,因此任何关于如何在现实世界中进行比较的信息都将受到赞赏.
我们来试试吧!
我将以下代码添加到StackOverflow的"问题"页面的副本中(首先删除现有脚本,并从头开始运行,其中一个timeit()每次都取消注释,三次运行100次操作:
function timeit(f) { var start= new Date(); for (var i=100; i-->0;) { f(); } return new Date()-start; } var c= document.getElementById('content'); var clones= []; //alert('cloneNode: '+timeit(function() { // clones.push(c.cloneNode(true)); //})) //alert('innerHTML: '+timeit(function() { // var d= document.createElement('div'); // d.innerHTML= c.innerHTML; // clones.push(d); //}))
以下是在Core 2 Q9300上的VirtualBox上运行的结果:
IE7 cloneNode: 3238, 3235, 3187 innerHTML: 8442, 8468, 8552 Firefox3 cloneNode: 1294, 1315, 1289 innerHTML: 3593, 3636, 3580 Safari3 cloneNode: 207, 273, 237 innerHTML: 805, 818, 786 Chrome1 cloneNode: 329, 377, 426 innerHTML: 2327, 2536, 2865 Opera10 cloneNode: 801, 791, 771 innerHTML: 1852, 1732, 1672
因此cloneNode(true)比复制innerHTML快得多.当然它总是会; 将DOM序列化为文本然后从HTML重新解析它是一项艰苦的工作.DOM子操作通常很慢的原因是你一个接一个地插入/移动它们; 像cloneNode这样的一次性DOM操作不必这样做.
Safari设法快速地完成innerHTML操作,但仍然没有像cloneNode那么快.正如预期的那样,IE是一只狗.
因此,对于每个说内部HTML都会明显更快而不考虑问题实际在做什么的人来说,自动-1.
是的,jQuery使用innerHTML进行克隆.不是因为它更快 - 阅读来源:
// IE copies events bound via attachEvent when // using cloneNode. Calling detachEvent on the // clone will also remove the events from the orignal // In order to get around this, we use innerHTML.
jQuery使用Element.attachEvent()来实现自己的事件系统,所以自然需要避免这个bug.如果您不需要,可以避免开销.
[偏离主题:再说一次,我认为将jQuery提升为最佳实践的顶峰可能有点误,特别是考虑到下一行:
html.replace(/ jQuery\d+="(?:\d+|null)"/g, "")
这是正确的 - jQuery将自己的任意属性添加到HTML元素中,然后在克隆它们时需要摆脱它们(或以其他方式提供对其标记的访问,例如通过$().html()方法).这很丑陋,但后来它认为最好的方法是使用正则表达式处理HTML,这是一种基本错误,你期望更多来自天真的1-reputation SO提问者而不是第二次来自最佳JS的作者框架Evar.
希望你的文本内容中没有任何字符串"jQuery1 ="2"",因为如果是这样你就会神秘地失去它.谢谢jQuery!因此,结束了偏离主题.]