優化javaScript代碼,提高執行效率


今天看完書,總結了一下可以如何優化 JavaScript 。

 

1.合並js文件

為優化性能,可以把多個js文件(css文件也可以)合並成極少數大文件。跟十個5k的js文件相比,合並成一個50k的文件更好。雖然代碼總字節數沒變,卻避免了多個HTTP請求造成的開銷。每個請求都會在客戶端和服務器兩邊有個建立和消除的過程,導致請求和響應header帶來開銷,還有服務器端更多的進程和線程資源消耗(可能還有為壓縮內容耗費的cpu時間)。除了HTTP請求,並發問題也很重要。默認情況下,在使用持久連接(persistent connections)時,ie和firefox在同一域名內只會同時下載兩個資源。這就意味着,在我們等待下載2個js文件的同時,將無法下載圖片資源。也就是說,這段時間內用戶在頁面上看不到圖片。

(這個方法有缺點:把所有資源一起打包,將強制用戶一次下載完所有資源,造成某些用戶不必要的開銷)

 

2、減緩代碼下載時間:

        Web瀏覽器下載的是javaScript的源碼、其中包含的長變量名、注釋、空格和換行等多余字符大大減緩了代碼下載的時間。這些字符對於團隊編寫時十分有效、但在最后工程完成上傳到服務器時、應當將它們全部刪除。例如:

  1. function showMeTheMoney(){  
  2.         if(!money){  
  3.                 return false;  
  4.         }else{  
  5.                 ...  
  6.         }  
  7. }  
Javascript代碼  可優化成:
  1. function showMeTheMoney(){if(!money){return false;}else{...}}  

        這樣、優化后就節約了25個字節、倘若是一個大的javaScript工程、將節省出非常大的空間、不但提高了用戶的下載速度、也減輕了服務器的壓力。相信這樣的代碼大家見過不少、很多優秀的js插件源碼都這么干!

        另外、對於布爾型的值true和false、true都可以用1來代替,而false可以用0來代替。對於true節省了3個字節、而false則節省了4個字節、例如

  1. var bSearch = false;  
  2.         for(var i=0;i<aChoices.length&&!bSearch;i++){  
  3.             if(aChoices[i] == vValue)  
  4.                 bSearch = true ;  
  5.         }  

替換成:

  1. var bSearch = 0;  
  2.         for(var i=0;i<aChoices.length&&!bSearch;i++){  
  3.             if(aChoices[i] == vValue)  
  4.                 bSearch = 1 ;  
  5.         }  

替換了布爾值之后、代碼的執行效率、結果都相同、但節省了7個字節。

代碼中常常會出現檢測某個值是否為有效值的語句、而很多條件非的判斷就判斷某個變量是否為"undefined"、"null"、或者"false"、例如:

  1. if(myValue != undefined){  
  2.             //...   
  3.         }  
  4.           
  5.         if(myValue !=null){  
  6.             //...   
  7.         }  
  8.           
  9.         if(myValue != false){  
  10.             //...   
  11.         }  

這些雖然都正確、但采用邏輯非操作符"!"也可以有同樣的效果、代碼如下:

  1. if(!myValue){  
  2.             //...   
  3.         }  

這樣的替換也可以節省一部分字節、而且不太影響代碼的可讀性。類型的代碼優化還有將數組定義時的 new Array()直接用"[]"代替、對象定義時的 new Object()用"{}"代替等、例如:

  1. var myArray = new Array();  
  2.         var myArray = [];  
  3.         var myObject = new Object();  
  4.         var myObject = {};  

顯然、第二行和第四行的代碼較為精簡、而且也很容易理解。

另外、在編寫代碼時往往為了提高可讀性、函數名稱、變量名稱使用了很長的英文單詞、同時也大大增加了代碼的長度、例如:

  1. function AddThreeVarsTogether(firstVar,secondVar,thirdVar){  
  2.             return (firstVar+secondVar+thirdVar);  
  3.         }  

可優化成:

  1. function A(a,b,c){return (a+b+c);}  

注意:在進行變量名稱替換時、必須十分小心、尤其不推薦使用文本編輯器的"查找"、"替換"功能、因為編輯器不能很好地區分變量名稱或者其他代碼。例如、希望將變量"tion"全部替換成"io"、很可能導致關鍵字"function"也被破壞。

對於上面說的這些減少代碼體積的方法、有一些很實用的小工具可以自動完成類似的工作、例如ECMAScript Cruncher、JSMin、Online JavaScript Compressor等。

 

3、合理聲明變量

        減少代碼的體積僅僅只能使得用戶下載的速度變快、但執行程序的速度並沒有改變。要提高代碼執行的效果、還得在各方面做調整。

        在瀏覽器中、JavaScript默認的變量范圍是window對象、也就是全局變量。全局變量只有在瀏覽器關閉才釋放。而JavaScript也有局部變量、通常在function中執行完畢就會立即被釋放。因此在函數體中要盡可能使用var關鍵字來聲明變量:

  1. function First(){  
  2.             a = "" ;   //直接使用變量   
  3.         }  
  4.         function Second(){  
  5.             alert(a);  
  6.         }  
  7.         First();  
  8.         Second();  
 

        這樣、變量"a"就成為了全局變量、直到頁面關閉時才會被銷毀、浪費了不必要的資源、如果在"a"的前面加上"var"、這樣"a"就成為了當前function的局部變量。在執行完First()便立即被銷毀。因此、在函數體中、如果不是特別需要的全局變量、都應當使用"var"進行聲明、從而節省系統資源。

 

4、使用內置函數縮短編譯時間

        只要可能、應當盡量使用JavaScript的內置函數。因為這些內置的屬性、方法都是用類似C、C++之類的言語編譯過的、運行起來比實時編譯的JavaScript快很多。例如計算指數函數、可以自己編寫:

  1. <html>  
  2.   <head>  
  3.     <base href="<%=basePath%>">  
  4.     <title>內置函數</title>  
  5.     <meta http-equiv="pragma" content="no-cache">  
  6.     <meta http-equiv="cache-control" content="no-cache">  
  7.     <meta http-equiv="expires" content="0">      
  8.     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  9.     <meta http-equiv="description" content="This is my page">  
  10.     <script type="text/javascript">  
  11.         function myPower(iNum,n){  
  12.             var iResult = iNum ;  
  13.             for(var i=0;i<n;i++)  
  14.                 iResult *= iNum ;  
  15.             return iResult;  
  16.         }  
  17.         var myDate1 = new Date();  
  18.         for(var i=0;i<150000;i++){  
  19.             myPower(7,8);  //自定義方法  
  20.         }  
  21.         var myDate2 = new Date();  
  22.         document.write(myDate2 - myDate1);  
  23.         document.write("<br/>");  
  24.         myDate1 = new Date();  
  25.         for(var i=0;i<150000;i++){  
  26.             Math.pow(7,8);  //采用系統內置方法  
  27.         }  
  28.         myDate2 = new Date();  
  29.         document.write(myDate2 - myDate1);  
  30.     </script>  
  31.   </head>  
  32.   <body>  
  33.   </body>  
  34. </html>  

運行的結果:在IE上使用定義的方法耗時2156ms,使用內置方法為750ms;  在firefox瀏覽器上,使用定義的方法耗時3625ms,使用內置方法為766ms;

 

5、合理書寫if語句

if語句恐怕是所有代碼中使用最頻繁的、然而很可惜的是它的執行效率並不是很高。在用if語句和多個else語句時、一定要把最有可能的情況放在第一個、然后是可能性第二的、依此類推。例如預計某個數值在0~100之間出現的概率最大、則可以這樣安排代碼:

  1. if(iNum>0&&iNum <100){  
  2.             alert("在0和100之間");  
  3.         }else if(iNum>99&&iNum<200){  
  4.             alert("在100和200之間");  
  5.         }else if(iNum>199&&iNum<300){  
  6.             alert("在200和300之間");  
  7.         }else{  
  8.             alert("小於等於0或者大於等於300");  
  9.         }  

總是將出現概率最多的情況放在前面、這樣就減少了進行多次測試后才能遇到正確條件的情況。當然也要盡可能減少使用else if 語句、例如上面的代碼還可以進一步優化成如下代碼:

  1. if(iNum>0){  
  2.             if(iNum<100){  
  3.                 alert("在0和100之間");  
  4.             }else{  
  5.                 if(iNum<200){  
  6.                     alert("在100和200之間");  
  7.                 }else{  
  8.                     if(iNum<300){  
  9.                         alert("在200和300之間");  
  10.                     }else{  
  11.                         alert("大於等於300");  
  12.                     }  
  13.                 }  
  14.             }  
  15.         }else{  
  16.             alert("小於等於0");  
  17.         }  

上面的代碼看起來比較復雜、但因為考慮了很多代碼潛在的判斷問題、執行問題、因此執行速度要較前面的代碼快。另外、通常當超過兩種情況時、最好能夠使用switch語句。經常用switch語句代替if語句、可令執行速度快甚至10倍。另外、由於case語句可以使用任何類型、也大大方便switch語句的編寫。

 

6、最小化語句數量

腳本找哦個的語句越少執行的時間就越短、而且代碼的體積也會相應減少。例如使用var定義變量時可以一次定義多個、代碼如下

  1. var iNum = 365;  
  2.         var sColor = "yellow";  
  3.         var aMyNum = [8,7,12,3] ;  
  4.         var oMyDate = new Date();  

上面的多個定義可以用var關鍵字一次性定義、代碼如下:

  1. var iNum = 365, sColor = "yellow" , aMyNum = [8,7,12,3],oMyDate = new Date() ;  

同樣在很多迭代運算的時候、也應該盡可能減少代碼量、如下兩行代碼:

  1. var sCar = aCars[i];  
  2.         i++;  

 可優化成:

  1. var sCar = aCars[i++];  
 

7、節約使用DOM

JavaScript對DOM的處理可能是最耗費時間的操作之一。每次JavaScript對DOM的操作都會改變頁面的表現、並重新渲染整個頁面、從而有明顯的時間消耗。比較快捷的方法就是盡可能不在頁面進行DOM操作、如下例中為ul添加了10個條目

  1. var oUl = document.getElementById("ulItem");  
  2.         for(var i=0;i<10;i++){  
  3.             var oLi = document.createElement("li");  
  4.             oUl.appendChild(oLi);  
  5.             oLi.appendChild(document.createTextNode("Item "+i));  
  6.         }  

以上代碼在循環中調用oUl.appendChild(oLi)、每次執行這條語句后、瀏覽器就會重新渲染頁面、其次給列表添加文本節點oLi.appendChild(document.createTextNode("Item "+i))、這也會造成頁面被重新渲染。因此每次運行都會造成兩次重新渲染頁面、共20次。

通常應當盡可能減少DOM的操作、將列表項目在添加文本節點之后在添加、並合理地使用createDocumentFragment()、代碼如下:

  1. var oUl = document.getElementById("ulItem");  
  2.         var oTemp = document.createDocumentFragment();  
  3.         for(var i=0;i<10;i++){  
  4.             var oLi = document.createElement("li");  
  5.             oLi.appendChild(document.createTextNode("Item "+i));  
  6.             oTemp.appendChild(oLi);  
  7.         }  
  8.         oUl.appendChild(oTemp);  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM