1. 程式人生 > >js性能的進階

js性能的進階

func UNC 性能提高 adding con png console rip ()

    為了說明js性能方面的差異用一個簡單的例子說明下,

    

<style>
		#ul1{
			padding: 5px;
			overflow: hidden;
		}
		#ul1 li{
			list-style: none;
			width: 15px;
			height: 15px;
			border-radius: 50%;
			background: #ccc;
			margin: 3px;
			float: left;
			cursor: pointer;
		}
		#ul1 .active{
			background: red;
		}
	</style>
<ul id="ul1">
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
...
</ul>

  

    這樣一個很簡單的列表。做成一個單選效果,給被點擊的li添加一個active的class。

    實現的發方法有很多種,我介紹4中,為了能清楚看到性能之間的差異,li元素我復制了2000個。

    第一種方法,也是最不可取,性能也是最浪費的一種

console.time("time1");
        $("#ul1 li").click(function(event) {
        console.time("time2");
            $("#ul1 li").removeClass(‘active‘);
            $(this).addClass(‘active‘);
            console.timeEnd(
"time2"); }); console.timeEnd("time1");

    這方法可能是初學者最易用到的,他的性能如下

技術分享圖片

首次事件綁定用了11ms ,之後每次點擊0.6ms左右,前幾次用的時間比較多。

     第二種方案

console.time("time1");
		var arrli = $("#ul1 li");
		arrli.click(function(event) {
		console.time("time2");
			arrli.removeClass(‘active‘);
			$(this).addClass(‘active‘);
			console.timeEnd("time2");
		});
		console.timeEnd("time1");

  技術分享圖片

    相對第一種情況首次花費時間多了,每次點擊花費時間少了,這次把jquery dom做了緩存沒有每次都進行dom選擇

    第三種方案,這種代碼量比較多,采用了dom緩存,和虛擬dom的概念。避免沒有必要的直接操作dom

    同時為了提高性避開使用query的選擇器

    

    

console.time("time1");
		var arrli = [];
		var lilist = document.querySelectorAll("#ul1 li");
		for(var i=0,len=lilist.length;i<len;i++){
			var jsn = {};
			jsn._active = false;//代表該元素的選中狀態[虛擬dom的概念]
			jsn.dom = $(lilist[i]);//把源生對象轉為query對象
			arrli.push(jsn);
			lilist[i].setAttribute("index",i);//添加一個數組中索引的屬性
			lilist[i].onclick = function(){
				console.time("time2");
				var index = this.getAttribute("index")*1;
				for(var i=0,len=arrli.length;i<len;i++){
					if(i === index){
						//只有在沒有選中的時候進行選中設置
						if(!arrli[i]._active){
							arrli[i]._active = true;
							arrli[i].dom.addClass(‘active‘);
						};
					}else{
						if(arrli[i]._active){
							arrli[i]._active = false;
							arrli[i].dom.removeClass(‘active‘);
						};
					};
				};
				console.timeEnd("time2");
			};
		};
		console.timeEnd("time1");

      看性能

技術分享圖片

    首次耗時4.6ms,使用原生的選擇器快了很多。每次點擊最多的一次耗時也是0.1ms,所以相對前兩種方案性能提高了很多。

    第四種方案

    基於第三種方案,每次點擊的時候會循環下,這種方案避開這種循環

  

console.time("time1");
		var arrli = [];
		var lilist = document.querySelectorAll("#ul1 li");
		var old = false;
		for(var i=0,len=lilist.length;i<len;i++){
			var jsn = {};
			jsn._active = false;//代表該元素的選中狀態[虛擬dom的概念]
			jsn.dom = $(lilist[i]);//把源生對象轉為query對象
			arrli.push(jsn);
			lilist[i].setAttribute("index",i);//添加一個數組中索引的屬性
			lilist[i].onclick = function(){
				console.time("time2");
				var index = this.getAttribute("index")*1;
				//這個方案不需要循環
				if(old){
					old._active = false;
					old.dom.removeClass(‘active‘);
				};
				if(!arrli[index]._active){
					arrli[index]._active = true;
					arrli[index].dom.addClass(‘active‘);
					old = arrli[index];
				};
				console.timeEnd("time2");
			};
		};
		console.timeEnd("time1");

       性能

    技術分享圖片

    相對第三種代碼改變並不多,性能方面每次點擊所花費的時間有所提高,缺點是後兩種增加了代碼量

js性能的進階