JavaScript 總結幾個提升性能知識點

前段時間花時間看了大半的《High Performance JavaScript》這本書啊,而後就開始忙項目了,慶幸最忙的一週已經熬過去了。因爲空不出時間,這個月寫的學習筆記也很少,忙完最苦X的一週,這兩天晚上也算是挑燈夜讀了...終因而在殘血之際將這本書shut down了...javascript

既然讀完了,總歸是要學到些什麼的。說說對這本書的見解先吧,總體的來講,內容仍是不錯的,就是感受有點老了(做爲前端小白,也多是自身水平有限,未能體會到其中真意)。看這本書的過程當中也是寫了挺多代碼用以測試的,而且對本書提倡的寫法和原先大衆的寫法的執行分別進行了斷點跟蹤,對於能實際測出的問題進行理解,固然,下斷點跟着執行也看不出的那也沒辦法咯。對於書中的知識點,這裏只是簡單的整理出我的所推崇的一部分,固然~ 不喜勿噴。css

針對js文件的加載位置前端

在HTML文件中,<script>標籤是能夠加在<head>區域和<body>區域的。這裏鑑於JavaScript執行和UI渲染的單線程緣由,若是js文件載入會阻塞後面對於頁面的解析過程,頁面會等到js文件徹底加載並運行後才繼續執行該作的操做。那麼問題就來了,這樣可能會出現頁面空白or卡頓現象。做爲一名前端開發,重要的不只僅止於實現了需求,應該還有優質的用戶體驗。那麼咱們就須要消除用戶枯燥的等待,針對這個問題,這裏有本獸想到的兩種解決方案:java

1.  若是js文件沒有特殊要求指明須要在頁面渲染以前載入及編譯完成的,那麼選擇將js文件放到</body>標籤前(既全部的頁面所呈現內容的後面),css文件仍是放到<head>區域(誰也不肯意看一個佈局雜亂無章的頁面)。這樣作就能先讓用戶看到有佈局的頁面而不是空白頁了,那麼也會有人指出:那數據得經過js請求加載進來啊,怎麼辦呢?能夠對數據的加載作排序,急需呈現的接口放前面執行,不是那麼須要的能夠延後執行,同時作個簡單的載入動畫or提示。數組

2.  若是這些js文件有指明須要先執行了,才能更好的展現頁面內容,那麼就在第一個js或者頁面上先放個載入小動畫,能夠一些有趣的或者萌萌的動畫場景。這樣也是能較好的避免用戶等待的無聊,說不定人家還對這個載入動畫更感興趣呢,這樣可提高項目的用戶體驗感。瀏覽器

最終推薦:將<script>標籤儘量的放到</body>標籤前面加載,以提高用戶體驗。app

針對js文件的合併
在不少團隊開發中,咱們可能會將不一樣功能的代碼塊分別放置在不一樣的js文件中,以便於開發過程當中衆人合做寫代碼會更加方便,畢竟只須要找對應文件夾或文件而不是在一個很長的文件中找一個方法。這確實是會提升團隊開發效率及新人加入後的更容易進行二次開發及維護。那麼將這個問題放到頁面性能裏呢?這正是問題所在,在這本書中指出:Each HTTP request brings with it additional performance overhead,so downloading one single 100 KB file will be faster than downloading four 25 KB files.框架

下載1個100KB的文件比下載4個25KB的文件要快,而開發過程當中區分開各個文件又有很大的好處,那麼合併這個問題也就放在開發完後再處理咯,相信這個操做你們都不會陌生吧,如今的前端工具這麼豐富,各位習慣用什麼壓縮就用什麼壓縮吧~
這裏簡單提出下,在載入文件方面還能夠用到defer和async屬性,用於延遲加載和異步加載,在現代瀏覽器中,大多數是已經支持defer屬性了,還沒習慣用這個額,也不知道具體會不會存在什麼問題。有興趣的朋友可自行google該知識點,這裏件簡單提下吧。異步

如今的框架也大多配合懶加載和按需加載了。async

更快速的數據訪問

對於瀏覽器來講,一個標識符所處的位置越深,去讀寫他的速度也就越慢(對於這點,原型鏈亦是如此)。這個應該不難理解,簡單比喻就是:雜貨店離你家越遠,你去打醬油所花的時間就越長... 熊孩子,打個醬油那麼久,菜早燒焦了 -.-~

若是咱們須要在當前函數內屢次用到一個變量值,那麼咱們能夠用一個局部變量先將其存儲起來,案例以下:

  //修改前
  function showLi(){
      var i = 0;
      for(;i<document.getElementsByTagName("li").length;i++){    //一次訪問document
          console.log(i,document.getElementsByTagName("li")[i]);  //三次訪問document
      };
  };
  //修改後
  function showLi(){
      var li_s = document.getElementsByTagName("li");  //一次訪問document
      var i = 0;
      for(;i<li_s.length;i++){
          console.log(i,li_s[i]);  //三次訪問局部變量li_s
      };
  };

DOM操做的優化

衆所周知的,DOM操做遠比javascript的執行耗性能,雖然咱們避免不了對DOM進行操做,但咱們能夠儘可能去減小該操做對性能的消耗。

讓咱們經過代碼解釋這個問題:

  function innerLi_s(){
      var i = 0;
      for(;i<20;i++){
          document.getElementById("Num").innerHTML="A"; //進行了20次循環,每次又有2次DOM元素訪問:一次讀取innerHTML的值,一次寫入值
      };
  };

針對以上方法進行一次改寫:

  function innerLi_s(){
      var content ="";
      var i = 0;
      for(;i<20;i++){
          content += "A";  //這裏只對js的變量循環了20次
      };
      document.getElementById("Num").innerHTML += content;  //這裏值進行了一次DOM操做,又分2次DOM訪問:一次讀取innerHTML的值,一次寫入值
  };

減小Dom的重繪重排版

元素佈局的改變或內容的增刪改或者瀏覽器窗口尺寸改變都將會致使重排,而字體顏色或者背景色的修改則將致使重繪。
對於相似如下代碼的操做,聽說現代瀏覽器大多進行了優化(將其優化成1次重排版):

  //修改前
  var ele = document.getElementById("div");
  document.body.appendChild(ele); //本例針對已存在DOM元素的操做作對比,添加動做產生1次重排
  ele.style.borderLeft = "1px"; //又1次重排版
  ele.style.borderRight = "2px"; //又1次重排版
  ele.style.padding = "5px"; //還有1次重排版
  //修改後
  var ele = document.getElementById("div");
  document.body.appendChild(ele); //添加動做產生1次重排
  el.style.cssText = "border-left:1px;border-right:2px;padding:5px"; //又1次重排版

上面代碼只是作個次數對比,若是是正常的作法,應該是如下代碼:

 var ele = document.getElementById("div");
  ele.style.borderLeft = "1px"; 
  ele.style.borderRight = "2px"; 
  ele.style.padding = "5px"; 
  document.body.appendChild(ele); //1次重排

針對已存在DOM的多重操做,如下三種方法也能夠減小重排版和重繪的次數:

1.Dom先隱藏,操做後再顯示 2次重排 (臨時的display:none)

2.document.createDocumentFragment() 建立文檔片斷處理,操做後追加到頁面 1次重排

3.var newDOM = oldDOM.cloneNode(true)建立Dom副本,修改副本後oldDOM.parentNode.replaceChild(newDOM,oldDOM)覆蓋原DOM 2次重排

循環的優化

這應該是較多人都知道的寫法了,簡單帶過便可(後面仍是用代碼+註釋形式說明)~

  //修改前
  var i = 0;
  for(;i<arr.lengthli++){  //每次循環都須要獲取數組arr的length
      console.log(arr[i]);
  }
  //修改後
  var i = 0;
  var len = arr.length;  //獲取一次數組arr的length 
  for(;i<len;i++){
      console.log(arr[i]);
  }
  //or
  var i = arr.length;;
  for(;i;i--){
      console.log(arr[i]);
  }

合理利用二進制

如:對2取模,則偶數最低位是0,奇數最低位是0,與1進行位與操做的結果是0,奇數的最低位是1,與1進行位與操做的結果是1。

代碼以下:

  .odd{color:red}
  .even{color:yellow}
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
    </ul>
  var i = 0;
  var lis = document.getElementsByTagName("li");
  var len = lis.length;
  for(;i<len;i++){
      if(i&1){
          lis[i].className = "even";
      } else{
          lis[i].className = "odd";
      }
  };

雖然說現代瀏覽器都已經作的很好了,可是本獸以爲這是本身對代碼質量的一個追求。而且可能一個點或者兩個點不注意是不會產生多大性能影響,可是從多個點進行優化後,可能產生的就會是質的飛躍了~

相關文章
相關標籤/搜索