Подтвердить что ты не робот

.append VS.html Производительность VS.innerHTML

Этот сайт запускает тест между 3 различными методами, и кажется, что .html - самый быстрый, а затем .append. сопровождаемый .innerHTML. Может кто-нибудь объяснить мне причины этого?

Здесь сайт, который делает сравнение среди трех методов.

Я прочитал этот ТАК вопрос, который связан, но я не совсем понимаю данный ответ, и этот вопрос мало что .innerHtml отношении .innerHtml.

Я не понимаю следующую часть:

Временный элемент создан, давайте назовем его x. x innerHTML установлен на строку HTML, которую вы передали. Затем jQuery перенесет каждый из созданных узлов (то есть, x childNodes) во вновь созданный фрагмент документа, который затем будет кешироваться в следующий раз. Затем он вернет фрагмент childNodes как свежую коллекцию DOM. Обратите внимание, что на самом деле все гораздо сложнее, так как jQuery выполняет несколько кросс-браузерных проверок и различные другие оптимизации. Например, если вы передадите просто <div></div> в jQuery(), jQuery будет использовать ярлык и просто сделает document.createElement('div').

Может кто-нибудь упростить это?

4b9b3361

Ответ 1

Этот показатель бесполезен. 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

Ответ 2

Все трое мне мешают. Модификация 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 составляет 26 тыс. Ops/sec против 1000, 10 000 и 13

enter image description here

Ответ 3

Как .html быть быстрее, чем .innerHTML, когда .html использует .innerHTML с большим количеством дополнительного кода? Здесь .html реализация в jQuery (взята непосредственно из файла 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 );
}

Ответ 4

Я думаю, что innerHTML быстрее с advesstion @Brat.

И при создании цикла и строки добавления должно быть полезно сначала использовать переменную. Это делает вашу работу более хорошей.

хороший код:

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

Ответ 5

У меня также была проблема с большим перерисованием таблицы (размером около 10x100). Чтобы перерисовать всю таблицу, требуется около 300 мс.

Причина не в 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

Как сказал Барт, innerHTML всегда быстрее, чем манипулирование DOM.

Я тестировал hyperHTML, поэтому я решил поделиться своими результатами. На самом деле я изначально не запускал свои тесты в CodePen, и есть интересная разница в том, что времена jQuery намного ближе к внутреннему, выполняемому в CodePen.

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