.append VS .html VS .innerHTML performance
该站点在3种不同方法之间进行了测试,看来
这是在三种方法之间进行比较的站点。
我已经阅读了这个与此相关的问题,但我不太理解给出的答案,并且该问题并未真正详细说明
我不理解以下部分:
A temporary element is created, let's call it x. x's innerHTML is set to the string of HTML that you've passed. Then jQuery will transfer each of the produced nodes (that is, x's childNodes) over to a newly created document fragment, which it will then cache for next time. It will then return the fragment's childNodes as a fresh DOM collection.
Note that it's actually a lot more complicated than that, as jQuery does a bunch of cross-browser checks and various other optimisations. E.g. if you pass justto jQuery(), jQuery will take a shortcut and simply do document.createElement('div').
有人可以简化吗?
这个基准毫无价值。
jQuery看起来更快,因为jQuery首先准备了所有HTML字符串,而其他的每次迭代都执行一个操作。还要注意,jQuery.html()尽可能使用
基准测试中的jQuery
1 2 3 4 5 6 | var html = ''; for (var i = 0; i < len; i++) { html += 'Test ' + i + ''; } $('#list').html(html); |
来自基准的innerHTML
1 2 3 4 | var list = document.getElementById('list'); for (var i = 0; i < len; i++) { list.innerHTML = list.innerHTML + 'Test ' + i + ''; } |
如果将
1 2 3 4 5 6 7 8 | var list = document.getElementById('list'); var html = ''; for (var i = 0; i < len; i++) { html += 'Test ' + i + ''; } list.innerHTML = html; |
http://jsben.ch/#/yDvKH
这三个对我都很慢。每次迭代修改dom都很慢。
http://jsperf.com/jquery-append-vs-html-list-performance/24
我刚刚在其中添加了一个新测试:
1 2 3 4 5 6 | var html = []; for (var i = 0; i < len; i++) { html.push('Test ' + i + ''); } document.getElementById('list').innerHTML = html.join(''); |
这又快得多了。 :)
我在Firefox中执行的方法的运行速度为26k Ops / sec,而速度为1,000、10,000和13
当
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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 ); } |
正如Bart所说,innerHTML总是比DOM操作更快。
我正在测试hyperHTML,所以我想分享一下我的结果。我最初实际上并没有在CodePen中运行基准测试,并且存在一个有趣的区别,即jQuery的时间与在CodePen中运行的innerHTML更加接近。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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检查引起的,这似乎是谨慎的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 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'; } |
我认为建议使用@Brat可以使innerHTML更快。
在创建循环和附加字符串时,最好先使用变量。
它使您的表现更加出色。
好代码:
1 2 3 4 5 | var html = ''; for (var i = 0; i < len; i++) { html += 'Test ' + i + ''; }; $('#list').append(html); |
效率不高的代码:
1 2 3 4 | for (var i = 0; i < len; i++) { var html = 'Test ' + i + ''; $('#list').append(html); } |
例如:http://jsben.ch/#/yDvKH