代码之家  ›  专栏  ›  技术社区  ›  levik

深度克隆与InnerHTML设置:什么更快?

  •  28
  • levik  · 技术社区  · 17 年前

    我正试图找出在浏览器中深度克隆DOM树的最有效方法。

    如果我从

    var div = document.getElementById("source");
    var markup = div.innerHTML;
    

    什么会更快,

    var target = div.cloneNode(true);
    

    var target = document.cloneNode(false);
    target.innerHTML = markup;
    

    我知道浏览器平台在这里可能会有很大的不同,所以任何关于这些在现实世界中的比较的信息都会受到赞赏。

    3 回复  |  直到 17 年前
        1
  •  48
  •   bobince    17 年前

    让我们来测试一下!

    我将以下代码添加到stackoverflow的问题页的副本中(首先删除现有脚本,然后从头开始运行,每次大约取消一个timeit()s的注释,运行三次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);
    //}))
    

    以下是运行在核心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
    

    所以克隆诺德(真)比复制innerhtml快得多。当然,总是这样;将一个DOM序列化为文本,然后从HTML重新解析它是一项艰巨的工作。dom子操作通常很慢的原因是您要逐个插入/移动它们;像clonenode这样的dom操作一次都不需要这样做。

    Safari以惊人的速度完成了InnerHTML操作,但仍然不如Clonenode快。如所料,这是一条狗。

    所以,自动-1的所有人谁说,innerhtml显然会更快,而不考虑问题实际上在做什么。

    是的,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,这是一种基本的错误,比起第二个即将到来的最佳JS框架evar的作者,你更希望从没有声誉的So提问者那里得到更多。

    希望您的文本内容中没有字符串__jquery1=“2”_157;,因为如果是这样,您只是神秘地丢失了它。谢谢JQuery!这样就把话题之外的话题撇开了。]

        2
  •  1
  •   levik    17 年前

    六羟甲基三聚氰胺六甲醚。。。有趣的是,我刚刚在firefox 3上做了一个测试,一个深度克隆比使用innerhtml路径快3倍。

    我敢肯定innerhtml仍然比单个的dom操作快,但至少对于深度克隆来说,clonenode(true)似乎是更好的优化。

        3
  •  -5
  •   Liorsion    17 年前

    一般来说,innerhtml更快。看看这个,A benchmark across many platforms :