JavaScript提高網站效能最佳化的建議(二)_javascript技巧

來源:互聯網
上載者:User

在javascript關於提高網站效能的幾點建議(一)中,從HTTP請求到頁面渲染幾個方面對提高網站效能提出了幾點建議,本文是學習Steve Sounders的另外一本書《高效能網站建設進階指南》之後,從JavaScript效能的角度進行總結概括,諸君共勉。

JavaScript效能是實現高效能Web應用程式的關鍵

——Steve Sounders

1 利用js範圍鏈

範圍鏈(scope chain)

當執行一段JavaScript代碼(全域代碼或函數)時,JavaScript引擎會建立為其建立一個範圍又稱為執行內容(Execution Context),在頁面載入後會首先建立一個全域的範圍,然後每執行一個函數,會建立一個對應的範圍,從而形成了一條範圍鏈。每個範圍都有一條對應的範圍鏈,鏈頭是全域範圍,鏈尾是當前函數範圍。

範圍鏈的作用是用於解析標識符,當函數被建立時(不是執行),會將this、arguments、具名引數和該函數中的所有局部變數添加到該當前範圍中,當JavaScript需要尋找變數X的時候(這個過程稱為變數解析),它首先會從範圍鏈中的鏈尾也就是當前範圍進行尋找是否有X屬性,如果沒有找到就順著範圍鏈繼續尋找,直到尋找到鏈頭,也就是全域範圍鏈,仍未找到該變數的話,就認為這段代碼的範圍鏈上不存在x變數,並拋出一個引用錯誤(ReferenceError)的異常。

管理好範圍鏈的深度,是一種只要少量工作就能提高效能的簡易方法,我們應避免因無意中增長了範圍鏈而導致執行速度變得緩慢。

使用局部變數(盡量縮短範圍鏈)

如果理解了範圍鏈的概念,那麼我們應該清楚JavaScript引擎對變數的解析時間跟範圍鏈的深度有關,顯而易見,局部變數由於處於鏈尾,存取速度是最快的,因此,一個好的經驗是:任何非局部變數使用超過一次時,請使用局部變數將其儲存下來,例如:

function changeDiv(){document.getELementById('myDiv').className = 'changed';document.getELementById('myDiv').style.height = 150;}

這裡myDiv這個dom元素被引用了兩次,為了更快的引用,我們應該用一個局部變數將其儲存下來,這樣做的好處不僅縮短了範圍鏈,而且避免了DOM元素的重複查詢:

function changeDiv(){var myDivStyle = document.getElementById('myDiv').style;myDiv.className = 300;myDiv.style.height = 150;}

避免使用with(不要增長範圍鏈)

一般在代碼執行過程中,函數的範圍鏈是固定的,然而with可以臨時增長函數的範圍鏈。with用於將對象屬性作為局部變數來顯示,使其便於訪問,例如:

var user = {name:'vicfeel',age:'23'};function showUser(){var local = 0;with(user){console.log("姓名" + name);console.log("年齡" + age);console.log(local);}}showUser();

這個例子中,通過with在showUser範圍鏈的鏈尾中又增加了一個臨時範圍,該範圍儲存著user對象的所有屬性,也就是增長了with這段代碼的範圍鏈,在這段代碼中,局部變數像local從鏈尾的第一個對象變成了第二個,自然減慢了標識符的存取。直到with語句結束,範圍鏈恢複增長。正因為with的這個缺陷,我們應盡量避免使用with關鍵字。

2 更合理的流量控制

JavaScript與其它程式設計語言一樣,擁有一些流量控制語句(迴圈、條件等),在每個環節上使用恰當的語句能極大的提高指令碼的運行速度。

快速條件判斷

提到條件判斷,首先要避免的一種使用方式:

if(value == 0){return result0;}else if(value == 1){return result1;}else if(value == 2){return result2;}else if(value == 3){return result3;}else if(value == 4){return result4;}else if(value == 5){return result5;}else if(value == 6){return result6;}else{return result7;}

這種使用if進行條件判斷的方式存在的主要問題是層次太深,當我要value = 7時,消耗時間要比value = 0長很多,大大損耗了效能,同時可讀性很差。

一種更好的方式,利用switch進行判斷。

swithc(value){case 0:return result0;case 1:return result1;case 2:return result2;case 3:return result3;case 4:return result4;case 5:return result5;case 6:return result6;default:return result7;}

這樣不僅提高了可讀性,查詢時間也要比if更快。但是如果只有一兩個條件時,if是比switch更快的

在JavaScript中,條件查詢還有另外一種方式,之前的例子是根據值返回不同的值,剛好可以利用數組實現hash表的映射查詢。

//定義數組var results = [result0,result1,result2,result3,result4,result5,result6,result7];//查詢結果return results[value];

這種數組的方式,在查詢範圍很大時才更加有效,因為它不必檢測上下邊界,只需要填入索引值就可以查詢了。它的局限性在於條件對應的是單一值,而不是一系列操作。因此要綜合實際情況,選擇合適的條件判斷方式,發揮效能最大化。

快速迴圈

JavaScript中存在4種迴圈方式for迴圈、do-while迴圈、while迴圈和for-in迴圈。下面是一個很常用的迴圈使用方式:

var values = [1,2,3,4,5];for(var i = 0;i < values.length;i++){process(values[i]);}

我們可以看到,這段代碼最明顯可以最佳化的地方在於values.length,每次迴圈i都要和values的長度進行比較,而查詢屬性要比局部變數更耗時,如果迴圈次數越大,這種耗時就越明顯,因此可以這樣最佳化:

var values = [1,2,3,4,5];var length = values.length;//局部變數儲存數組長度for(var i = 0;i < length;i++){process(values[i]);}

這段代碼還可以繼續最佳化,將迴圈變數遞減到0,而不是遞加到總長度。

var values = [1,2,3,4,5];var length = values.length;for(var i = length;i--;){ //遞減到0process(values[i]);}

這裡將迴圈結束改造為與0比較,所以每個迴圈的速度更快了,根據迴圈的複雜度不同,這種簡單改變可以比原來節約大概50%的時間。

聯繫我們

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