代码改变世界

createElement与innerHtml性能比較

2017-07-04 10:05  tlnshuju  阅读(547)  评论(0编辑  收藏  举报

        js中。动态加入html的方法大致就是两种,一种是document.createElement等方法创建,然后使用Element.appendChild加入,或者是使用Element.innerHTML = sHTML的方式。两种方法,显然前面一种更加灵活,除了Element.appendChild方法外,还有insertBefore等等其它dom操作方式。这里且不谈灵活性,但就性能做一个探索。

       比較的方式非常easy:

       各生成10000次形如<div><span>性能測试</span> ......</div>的html,然后一次性放入body中。记录此全过程,耗时时间,并执行10次,输出耗时。

       代码例如以下:

	window.onload = function(){
		testPerformance(10,function(){
			document.body.appendChild(generateHtmlElement(10000));
		})
		testPerformance(10,function(){
			document.body.innerHTML = generateHtmlString(10000);
		})
	}
	
	function testPerformance(iTimes,fn){
		var iLastTime = null;
		var iTotalTime = 0;
		for(var i=1;i<=iTimes;++i){
			iLastTime = new Date().getTime();
			fn();
			var iCost = new Date().getTime() - iLastTime;
			console.log("第"+i+"次用时:"+iCost+"毫秒");
			iTotalTime+=iCost;
			document.body.innerHTML = "";
			iLastTime = new Date().getTime();
		}
		console.log("总用时:"+iTotalTime+"毫秒");
		console.log("平均用时:"+iTotalTime/iTimes+"毫秒");
	}
	
	/*
	 *使用document.createElement等dom方法生成元素<div><span>測试性能</span>....<div>
	 *times:生成div的数量
	 *return Element
	 */
	function generateHtmlElement(iTimes){
		var result = document.createElement("div");
		for(var i=0;i<iTimes;++i){
			var eDiv = document.createElement("div");
			
			for(var j = 0;j<10;++j){
				var eSpan = document.createElement("span");
				eSpan.appendChild(document.createTextNode("測试性能"));
				eDiv.appendChild(eSpan);
			}
			result.appendChild(eDiv);
		}
		return result;
	}
	/* 
   *使用字符串拼接的方式生成<div><span>測试性能</span>....<div>字符串
   *times:生成div的数量 
   *return string 
   */
	function generateHtmlString(iTimes){
		var sb = new StringBuilder ();
		
		for(var i=0;i<iTimes;++i){
			sb.append("<div>");
			for(var j = 0;j<10;++j){
				sb.append("<span>性能測试</span>");
			}
			sb.append("</div>");
		}
		return sb.toString();
	}
	
	function StringBuilder () {
     this.__asBuilder = [];
	}

	StringBuilder.prototype.clear = function(){
	     this.__asBuilder = [];//这样的写法要比this.__asBuilder.length = 0稍快,快多少。看数组的长度
	}
	
	StringBuilder.prototype.append = function(){
	     Array.prototype.push.apply(this.__asBuilder,arguments);//调用Array的push方法,这样调用。使用append,能够传递多个參数
	     return this;//这样能够实现append("a").append()的效果
	}
	
	StringBuilder.prototype.toString = function(){
	     return this.__asBuilder.join("");    
	}


拼接字符串的过程中,使用了一个自己定义类StringBuilder,以提升字符串拼接性能。

測试结果例如以下:

chrome下,差不太多,innerHTML稍好一些:


Firefox中,innerHTML完爆createElement


IE11,应该说,IE11,被chrome和Firefox完爆了

总结一下,单就性能而言,innerHTML都要比createElement创建元素在append进dom中快一些。在IE下。就差的更远了。话说,IE,你怎么这么慢?。我測试方式有问题么?!