【翻譯】最佳化JavaScript代碼的幾點建議

來源:互聯網
上載者:User

   用戶端指令碼能夠使得應用更加具有吸引力,但是瀏覽器對指令碼代碼的解釋執行可能也會導致效率低下。

   這裡我們探討幾個最佳化JavaScript代碼的最佳實務建議。

 

1、處理字串

      字串拼接在IE 6、7下的記憶體回收效能很差。雖然IE 8已經解決了這個問題。如果你的使用者中有相當一部分人使用IE 6、7,那麼你得謹慎構建你的字串了。     

      比如這個例子:

var veryLongMessage ='This is a long string that due to our strict line length limit of' +maxCharsPerLine +' characters per line must be wrapped. ' +percentWhoDislike +'% of engineers dislike this rule. The line length limit is for ' +' style purposes, but we don't want it to have a performance impact.' +' So the question is how should we do the wrapping?';

      不要直接使用字串拼接 + ,更好的做法是用join:

var veryLongMessage =['This is a long string that due to our strict line length limit of',maxCharsPerLine,' characters per line must be wrapped. ',percentWhoDislike,'% of engineers dislike this rule. The line length limit is for ',' style purposes, but we don't want it to have a performance impact.',' So the question is how should we do the wrapping?'].join();

      類似的,在條件分支語句或迴圈語句中使用字串拼接也很低效。不好的做法:

var fibonacciStr = 'First 20 Fibonacci Numbers';for (var i = 0; i < 20; i++) {fibonacciStr += i + ' = ' + fibonacci(i) + '';}

      正確的做法:

var strBuilder = ['First 20 fibonacci numbers:'];for (var i = 0; i < 20; i++) {  strBuilder.push(i, ' = ', fibonacci(i));}var fibonacciStr = strBuilder.join('');
 

2、使用helper functions構建字串片段

      通過將string builder傳入helper function來避免臨時儲存消耗。

      例如不該用下面這種:

var strBuilder = [];for (var i = 0, length = menuItems.length; i < length; i++) {  strBuilder.push(this.buildMenuItemHtml_(menuItems[i]));}var menuHtml = strBuilder.join();

      而應該使用:

var strBuilder = [];for (var i = 0, length = menuItems.length; i < length; i++) {  this.buildMenuItem_(menuItems[i], strBuilder);}var menuHtml = strBuilder.join();

 

3、定義類方法

     下面的代碼是低效的,因為每次有一個baz.Bar執行個體被建立,一個新的函數和閉包就為foo建立:

baz.Bar = function() {  // constructor body  this.foo = function() {  // method body  };}

       更優的做法是:

baz.Bar = function() {  // constructor body};baz.Bar.prototype.foo = function() {  // method body};

       通過這種方法,不管有多少個baz.Bar執行個體被建立,只有一個function被建立,並且也不形成閉包。

 

4、初始化執行個體變數

      將執行個體變數的聲明/初始化放到prototype中,如果執行個體變數帶有一個實值型別的初始值(即number、Boolean、null、undefined或字串類型值)。這避免了每次構造器建立時都運行毫無意義的初始化代碼。

      不好的做法:

foo.Bar = function() {  this.prop1_ = 4;  this.prop2_ = true;  this.prop3_ = [];  this.prop4_ = 'blah';};

      更優的做法:

foo.Bar = function() {  this.prop3_ = [];};foo.Bar.prototype.prop1_ = 4;foo.Bar.prototype.prop2_ = true;foo.Bar.prototype.prop4_ = 'blah';

 

5、避免閉包中的陷阱

      閉包是一個強大有用的東西。但是他們有一些缺點,包括:

1、他們是記憶體泄露的最主要元兇2、建立一個閉包比建立一個內嵌函式慢,比重用一個靜態函數更慢。

      比如:

function setupAlertTimeout() {  var msg = 'Message to alert';  window.setTimeout(function() { alert(msg); }, 100);}

      比下面的代碼更慢:

function setupAlertTimeout() {  window.setTimeout(function() {    var msg = 'Message to alert';    alert(msg);  }, 100);}

      上面的代碼又比下面的代碼更慢:

function alertMsg() {  var msg = 'Message to alert';  alert(msg);}function setupAlertTimeout() {  window.setTimeout(alertMsg, 100);}

      閉包增加了一層範圍鏈。當瀏覽器解析屬性時,每一層的範圍鏈都必須被檢查。在下面的例子:

var a = 'a';function createFunctionWithClosure() {  var b = 'b';  return function () {    var c = 'c';    a;    b;    c;  };}var f = createFunctionWithClosure();f();

       當f被調用時,引用a比引用b更慢,引用b又比引用c更慢。

       查看IE+JScript Performance Recommendations Part 3: JavaScript Code inefficiencies 來擷取更多在IE下正確使用閉包的資訊

 

6、避免with

      避免在代碼中使用with語句。它對效能產生負面影響,因為它改變了範圍鏈,使得在其它範圍中尋找變數的代價更加昂貴。

 

7、避免瀏覽器記憶體泄露

      記憶體泄露是web應用中的常見問題,會導致巨大的效能問題。當瀏覽器消耗的記憶體增加,你的其他Web應用以及使用者系統的其他程式都會變得很慢。最常見的記憶體泄露情境是JavaScript引擎和瀏覽器的DOM對象的循環相依性,比如下面這個例子:

<script language='javascript'>   var menu = document.getElementById('myMenu');   AttachEvent(menu);   function AttachEvent(element) {      element.attachEvent( "onmouseover", mouseHandler);      function mouseHandler(){ /* whatever */ }   }</script>
       又比如下面的代碼:
var myGlobalObject;function SetupLeak(){   //Here a reference created from the JS World     //to the DOM world.    myGlobalObject=document.getElementById("LeakedDiv");    //Here DOM refers back to JS World;     //hence a circular reference.    //The memory will leak if not handled properly.    document.getElementById("LeakedDiv").expandoProperty = myGlobalObject;}
       更多資訊可以參考:http://www.javascriptkit.com/javatutors/closuresleak/index.shtml
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.