高效能JavaScript 編程實踐

來源:互聯網
上載者:User

標籤:

前言

  最近在翻《高效能JavaScript》這本書(2010年版 丁琛譯),感覺可能是因為瀏覽器引擎的改進或是其他原因,書中有些原本能提高效能的代碼在最新的瀏覽器中已經失效。但是有些章節的有些內容還是相當不錯的,譬如第八章編程實踐,為了方便以後的查閱,對此做個總結。失效的代碼也會在以後做更進一步的探索。

避免雙重求值

  這個最佳化策略很好理解,我們可能都已經不知不覺地運用在了實際的編程中:

// not use thissetTimeout(‘alert("hello world")‘, 1000);// use thissetTimeout(function() {  alert(‘hello world‘);}, 1000);

  上面的兩段代碼都能執行,但是我們一般用第二種,同樣的對於setInterval來說也是如此,類似的還有eval()以及Function()建構函式。JavaScript像其他很多指令碼語言一樣,允許你在程式中提取一個包含代碼的字串,然後動態執行它。當你在JavaScript代碼中執行另一段JavaScript代碼時,都會導致雙重求值的效能消耗,此代碼首先會以正常的方式求值,然後在執行過程中對包含於字串中的代碼發起另一個求值運算。所以,大多數時候沒必要使用eval()和Function(),就避免使用它們;至於setTimeout和setInterval,建議傳入函數而不是字串來作為第一個參數。

  由此聯想到了php中的‘‘和“”,我們盡量用‘‘去引用字串,也是同樣的原因。

使用Object/Array直接量
// use thisvar obj = {  name: ‘hanzichi‘,  age: 10};var arr = [0, 1, 2, 3];// not use thisvar obj = new Object();obj.name = ‘hanzichi‘;obj.age = 10;var arr = new Array();arr[0] = 0;arr[1] = 1;arr[2] = 2;arr[3] = 3;
不要重複工作

  也許最常見的重複工作就是瀏覽器探測(當然“不要重複工作”只是一種思想,並不一定針對瀏覽器探測)。

  考慮一個添加事件處理器的例子,典型的跨瀏覽器代碼寫法如下:

function addHandler(target, eventType, handler) {   if (target.addEventListener) {  // DOM2 Events    target.addEventListener(eventType, handler, false);  } else {  // IE    target.attachEvent(‘on‘ + eventType, handler);  }}           addHandler(document, ‘click‘, function() {  console.log(‘hello world‘);});

  但是如果一個頁面調用了好多次addHandler函數添加事件,每次都會去做瀏覽器的判斷,但是事實是每次的判斷結果都是一樣的,因為瀏覽器並不會變化,這時我們就可以針對“不要重複工作”做一個最佳化策略。

  • 消極式載入

  消極式載入,也稱惰性載入,惰性載入等。消極式載入意味著在資訊被使用前不會做任何操作

function addHandler(target, eventType, handler) {   if (target.addEventListener) {  // DOM2 Events    addHandler = function(target, eventType, handler) {      target.addEventListener(eventType, handler, false);    };  } else {  // IE    addHandler = function(target, eventType, handler) {      target.attachEvent(‘on‘ + eventType, handler);    };  }  addHandler(target, eventType, handler);}           // 調用addHandler(document, ‘click‘, function() {  console.log(‘hello world‘);});addHandler(window, ‘keydown‘, function() {  console.log(‘key down‘);});

  方法在第一次被調用時,會先檢查並決定使用哪種方法去綁定事件處理器,然後原始函數被包含正確操作的新函數覆蓋。最後一步調用新的函數(也可以直接return 新的函數),並傳入原始參數。之後的每次調用addHandler()都不會再做檢測,因為檢測代碼已經被新的函數覆蓋。

  調用消極式載入函數時,第一次總會消耗較長的時間,因為它必須運行檢測接著再調用另一個函數完成任務,但隨後調用函數會變快,因為不需要再進行檢測。當一個函數在頁面中不會立即調用時,消極式載入是最好的選擇。

  • 條件預先載入

  條件預先載入會在指令碼載入期間提前檢測,而不會等到函數被調用:

var addHandler = document.addEventListener ?   function(target, eventType, handler) {    target.addEventListener(eventType, handler, false);  }:  function(target, eventType, handler) {    target.attachEvent(‘on‘ + eventType, handler);  };    // 調用addHandler(document, ‘click‘, function() {  console.log(‘hello world‘);});addHandler(window, ‘keydown‘, function() {  console.log(‘key down‘);});

  條件預先載入確保所有函數消耗的時間相同,其代價是需要在指令碼載入時就檢測,而不是載入後。預先載入適用於一個函數馬上就要被用到,並且在整個頁面的生命週期中頻繁出現的場合。

 

  常見的“不要重複工作”還有做ajax時候的瀏覽器探測,自己可以思考下寫寫代碼。

使用速度快的部分
  • 位元運算

  用位元運算加速大家都應該熟悉並且熟練掌握:

// use &1 instead of %2var a = 10;if (a & 1) {  // use this  // ...}if (a % 2) { // not use this  // ...}// use << 1 instead of *2var a = 10;var b = a << 1; // use thisvar b = a * 2;  // not use thisvar a = 10;var b = a >> 1; // use thisvar b = a / 2;  // not use this

  位元運算除了能加速快,還能用在各種演算法和資料結構中,比如狀態壓縮dp,按位dp等等。

  • 原生方法

  無論你的JavaScript代碼如何最佳化,都永遠不會比JavaScript引擎提供的原生方法更快,因為JavaScript原生部分在你寫代碼前就已經存在在瀏覽器中了,並且都是用底層語言寫的,諸如C++。這意味著這些方法會被編譯成機器碼,成為瀏覽器的一部分。

  所以盡量用一些內建的函數或者常量,比如Math對象提供的:

Math.EMath.LN10Math.LN2Math.PIMath.SQRT1_2Math.abs()Math.sin()Math.sqrt()...

  另外一個例子是選取器API,它允許使用CSS選取器來尋找DOM節點。CSS查詢被JavaScript原生支援並被JQuery發揚光大。JQuery引擎被廣泛認為是最快的CSS查詢引擎,但是它仍然比原生方法慢。原生的querySelector()和querySelectorAll()方法完成任務平均所需時間是基於JavaScript的CSS查詢的10%。所以當原生方法可用時,盡量使用它們。特別是數學運算和DOM操作,用編譯後的代碼做更多的事情,你的代碼就會越快。

高效能JavaScript 編程實踐

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.