.append VS .html VS .innerHTML表现

时间:2013-08-23 03:01:17

标签: javascript jquery

此网站在3种不同方法之间进行测试,似乎.html最快,其次是.append。然后是.innerHTML。有人可以向我解释原因吗?

这是三种方法中的site which does the comparison

我已阅读此this SO question这是相关的,但我并不理解给定的答案,而且这个问题并没有真正详细阐述.innerHtml

我不明白以下部分:

  

创建一个临时元素,我们称之为x。 x的innerHTML设置为您传递的HTML字符串。然后jQuery将每个生成的节点(即x的childNodes)转移到新创建的文档片段,然后它将被缓存以供下次使用。然后它将片段的childNodes作为新的DOM集合返回。   请注意,它实际上要复杂得多,因为jQuery会进行一系列跨浏览器检查和各种其他优化。例如。如果你只将<div></div>传递给jQuery(),jQuery将采用一个快捷方式,只需执行document.createElement('div')。

有人可以简化这个吗?

7 个答案:

答案 0 :(得分:42)

该基准毫无价值。 innerHTML总是比DOM操作更快。

jQuery 似乎更快,因为它首先准备一个包含所有HTML的字符串,而其他人每次迭代都会执行一次操作。另请注意,jQuery.html()会尽可能使用innerHTML

来自基准测试的jQuery

var html = '';
for (var i = 0; i < len; i++) {
  html += '<div>Test ' + i + '</div>';
}

$('#list').html(html);
来自基准的

innerHTML
var list = document.getElementById('list');
for (var i = 0; i < len; i++) {
  list.innerHTML = list.innerHTML + '<div>Test ' + i + '</div>';
}

innerHTML的测试如果写得像:

那么会快得多
var list = document.getElementById('list');
var html = '';

for (var i = 0; i < len; i++) {
    html += '<div>Test ' + i + '</div>';
}

list.innerHTML = html;

http://jsben.ch/#/yDvKH

答案 1 :(得分:41)

这三个对我来说都很慢。 每次迭代修改dom都很慢。

http://jsperf.com/jquery-append-vs-html-list-performance/24

我刚刚在那里添加了一个新测试:

var html = [];
for (var i = 0; i < len; i++) {
  html.push('<div>Test ' + i + '</div>');
}

document.getElementById('list').innerHTML = html.join('');

再次快得多。 :)

我在Firefox中的方法执行26k Ops / sec与1,000,10,000和13

enter image description here

答案 2 :(得分:11)

.html使用带有大量额外代码的.innerHTML时,.html如何比.innerHTML更快?这里是jQuery中的.html实现(直接取自jQuery文件)。

html: function( value ) {
    return jQuery.access( this, function( value ) {
        var elem = this[0] || {},
            i = 0,
            l = this.length;

        if ( value === undefined ) {
            return elem.nodeType === 1 ?
                elem.innerHTML.replace( rinlinejQuery, "" ) :
                undefined;
        }

        // See if we can take a shortcut and just use innerHTML
        if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
            ( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&
            ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
            !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {

            value = value.replace( rxhtmlTag, "<$1></$2>" );

            try {
                for (; i < l; i++ ) {
                    // Remove element nodes and prevent memory leaks
                    elem = this[i] || {};
                    if ( elem.nodeType === 1 ) {
                        jQuery.cleanData( getAll( elem, false ) );
                        elem.innerHTML = value;
                    }
                }

                elem = 0;

            // If using innerHTML throws an exception, use the fallback method
            } catch(e) {}
        }

        if ( elem ) {
            this.empty().append( value );
        }
    }, null, value, arguments.length );
}

答案 3 :(得分:2)

我认为使用suggesstion @Brat,innerHTML更快。

在创建循环和附加字符串时,应首先使用变量。 这会让你的表现更加出色。

好的代码:

var html = '';
for (var i = 0; i < len; i++) {
  html += '<div>Test ' + i + '</div>';
};
$('#list').append(html);

效率不高的代码:

for (var i = 0; i < len; i++) {
  var html = '<div>Test ' + i + '</div>';
  $('#list').append(html);
}

例如:http://jsben.ch/#/yDvKH

答案 4 :(得分:2)

如Bart所说, innerHTML总是比DOM操作快

我正在测试hyperHTML,所以我想分享一下我的结果。我最初实际上并没有在CodePen中运行基准测试,并且存在一个有趣的区别,即jQuery的时间与在CodePen中运行的innerHTML更加接近。

Chrome:
createFragment 312.80 ms  
hyperHTML      253.10 ms     
innerHTML       62.70 ms   
$.append       183.40 ms

Chrome (extensions off): 
createFragment 225.10 ms 
hyperHTML      139.80 ms 
innerHTML       47.80 ms 
$.append       170.90 ms

Firefox: 
createFragment 141 ms 
hyperHTML       84 ms 
innerHTML       25 ms 
$.append        90 ms

Edge: 
createFragment 422.50 ms 
hyperHTML      184.60 ms 
innerHTML       44.00 ms 
$.append      1629.69 ms

IE11: 
createFragment   1180.29 ms 
hyperHTML       13315.59 ms //slow fallbacks, IE sucks 
innerHTML         125.70 ms 
$.append         2382.49 ms

我认为这非常简单。 JavaScript在解析和创建元素时不如浏览器快,因为浏览器是机器特定的编译代码。除了传递HTML并让浏览器无间断地工作之外,您做得更好。

某些性能差异可能是由于XSS检查引起的,这似乎是谨慎的。

function runbench(){
  var data = [];
  for (var i = 0; i < 10001; i++) {
      data.push("<span>" + i + "</span>");
  }

  var perf=[];
  var t0 = performance.now();
  var c = document.createDocumentFragment();
  for (var i = 0; i < 10001; i++) {
      var e = document.createElement("span");
      e.innerHTML = data[i];
      c.appendChild(e);
  }
  document.querySelector('#createFragment').appendChild(c);
  document.querySelector('#createFragment').classList='done';
  var t1 = performance.now();
  perf.push(t1-t0);

  var t0 = performance.now();
  document.querySelector('#innerHTML').innerHTML = data.join('');
  document.querySelector('#innerHTML').classList='done';
  var t1 = performance.now();
  perf.push(t1-t0);

  var t0 = performance.now();
  $('#jqhtml').html(data.join(''));
  document.querySelector('#jqhtml').classList='done';
  var t1 = performance.now();
  perf.push(t1-t0);

  var t0 = performance.now();
  $('#jqappend').append(data.join(''));
  document.querySelector('#jqappend').classList='done';
  var t1 = performance.now();
  perf.push(t1-t0);

  var t0 = performance.now();
  hyperHTML.bind(document.querySelector('#hyperHTML'))       
  `${data.map(function (item) {
      return "<span>" + item + "</span>";
  })}`;
  document.querySelector('#hyperHTML').classList='done';
  var t1 = performance.now();
  perf.push(t1-t0);

  var stats = [];
  stats.push("<table>")
  stats.push("<tr><td>createFrag: </td><td>" + perf[0].toFixed(2) + "</td></tr>");
  stats.push("<tr><td>innerHTML: </td><td>" + perf[1].toFixed(2) + "</td></tr>");
  stats.push("<tr><td>$.html: </td><td>" + perf[2] .toFixed(2) + "</td></tr>");
  stats.push("<tr><td>$.append: </td><td>" + perf[3] .toFixed(2) + "</td></tr>");
  stats.push("<tr><td>hyperHTML: </td><td>" + perf[4].toFixed(2) + "</td></tr>");
  stats.push("</table>");
  $('#performance').html(stats.join(''));
  document.querySelector('#performance').classList='done';
}

https://codepen.io/jwhooper/pen/GzKwMV

答案 5 :(得分:1)

我也遇到了大表重绘(大约10x100大小)的问题。重绘整个表大约需要300ms。

原因不是在jQuery.append()中而是在dom.innerHTML中,而是每次附加每个元素。

最快的方法是连接所有元素html代码,然后将其附加到DOM。 像这样:

function redrawMyTable( myData )
{
    var innerHTML = '';
    for ( var i = 0; i < myData.length; i++ )
    {
      innerHTML += createRowFromData( myData[i] );
    }

    myTableTbody.innerHTML = innerHTML;
}
function createRowFromData( rowData )
{
    var rowHTML = '';
    for ( var i = 0; i < rowData.length; i++ )
    {
      rowHTML += createCellFromData( rowData[i] );
    }
    return rowHTML;
}
function createCellFromData( cellData )
{
    //Do everything you need, and return HTMl code as a string
    return cellHTML;
}

现在它只需要20-30毫秒(相对于300毫秒:))

答案 6 :(得分:0)

6年后

重点是-不要操纵实时DOM。在外面做。今天,在哪里都无所谓。您可以使用HTML字符串,DocumentFragment(不包括Internet Explorer)或创建新元素,但不要将其添加到DOM中,而是根据需要进行填充,然后添加。

在Chrome和Firefox上,我的观察是运行时间都是相同的,付出或付出几个百分点。

不再需要在存储在数组中的块中构建长HTML字符串,然后再进行join('')-ed。几年前,我测量了巨大的时差。今天不行。第一点:在Chrome和FF上没有可识别的时差,第二点:此时并没有浪费时间,而是在渲染中。