《高性能網站建設進階指南》知識摘錄

##《高性能網站建設進階指南》知識摘錄 現在,許多網站和項目的整個用戶界面都是用JavaScript來實現的,因此若是對JavaScript進行優化,或許對網站的性能提高會有所幫助,下面介紹幾種編寫高效JavaScript的方法javascript


###使用局部對象 當執行JavaScript代碼時,JavaScript引擎會建立一個執行上下文,當頁面加載時,JavaScript引擎也會在頁面加載後建立一個全局的執行上下文。每一個執行上下文都有一個與之關聯的做用鏈域,用於解析標識符。全局執行上下文的做用鏈域中只有一個變量對象,它定義了JavaScript中全部可用的全局對象和函數,當函數被建立(不是執行)時,JavaScript引擎會把建立時執行上下文的做用鏈域賦給函數的內部屬性[scope],而後,當函數被執行時,JavaScript引擎會建立一個活動對象,並在初始化時給this,arguments,命名參數和該函數的全部局部變量賦值。java

JavaScript引擎在解析標識符的時候,它首先查找從做用鏈中的第一個對象開始,這個對象就是包含該函數局部變量的活動對象。若是在該對象中沒有找到標識符,就會繼續在做用鏈域中的下一個對象裏查找標識符,一旦找到標識符,查找就結束。數組

到目前爲止,局部變量是JavaScript中讀寫最快的標誌符,由於它們存在於執行函數的活動對象中,解析標識符只須要查找做用鏈域中的單個對象,讀取變量值的總耗時隨着查找做用鏈域的逐層深刻而不斷增加,因此標識符越深存取速度越慢。以下代碼所示:瀏覽器

function createChildFor(eleId){
    var ele = document.getElementById(eleId),
    newEl = document.createElement('div');
    element.appendChild(newEl);
  }

在上面這段代碼中,這個函數引用了兩次全局變量document,由於document使用超過了一次,因此咱們能夠改進爲以下代碼:數據結構

function createChildFor(eleId){
    var doc = document,
    var ele = doc.getElementById(eleId),
    newEl = doc.createElement('div');
    element.appendChild(newEl);
  }

###避免增加做用鏈域 在代碼執行過程當中,執行上下文對應的做用域鏈一般保持不變,然而有兩個語句會臨時增長執行上下文的做用鏈域,以下面的代碼:app

var person = {
    name:'sunshine',
    age:99
 };
 function displayInfo(){
    var count = 5;
    with(person){
       alert(count);
     }
 }

如上所示,person對象傳入了with語句塊,這樣就能夠像訪問局部變量同樣訪問nameage屬性了。實際上它是將一個新的變量對象添加到執行上下文做用域的頂部 Alt text函數

這樣你在訪問內部變量count的時候,它的訪問層級也會相應變深,因此性能就會降低性能

第二個會增加做用鏈域的是try-catch語句塊中的catch從句。在執行catch從句中的代碼時,其行爲方式相似於with語句,也就是在做用鏈域的頂部增長了一個對象,該對象包含了由catch指定命名的異常對象,然而,因爲catch從句僅在執行try從句發生錯誤時才執行,因此它比with語句的影響要小。優化

###高效的數據存儲 通常而言,在腳本中有4種地方能夠存取數據:網站

  • 字面量值
  • 變量
  • 數組元素
  • 對象屬性

在大多數瀏覽器中,從字面量中讀取值和從局部變量中讀取值得開銷差別很小,真正的差別在於從數組或者對象中讀取數據,存取這些數據結構中的某個值,以下代碼所示:

function fun(data){
     if(data.count > 0){
	    for(var i = 0;i<data.count;i++){
		    //do somethine
		}
	 }
  }

將上面那段代碼改寫成以下所示:

示:

function fun(data){
  var count = count; //將對象的屬性存在變量字面量中
     if(count > 0){
	    for(var i = 0;i<count;i++){
		    //do somethine
		}
	 }
  }

下面這段代碼,就會直接去讀取count字面量的值,而不是再去讀取對象的屬性值,這樣在性能上也有所提高。同理可得:存取data.countdata.item.count

###快速條件判斷 在條件有不少的狀況下,究竟是使用if-else仍是switch,if-elseswitch的結構相信你們都已經很熟悉了,在這裏我就再也不贅述了,下面還提供一種方法,數組查詢方法

var results = [result0,result1,result2,result3,result4,result5];
  return results[value];

下面就這三種方法給出一種統一的選擇方案:

  • 使用if語句的狀況 ---兩個以內的離散值須要判斷 ---大量的值能容易地等到不一樣的區間範圍中
  • 使用switch語句的狀況 --- 超過兩個而少於10個離散值須要判斷 ---條件是非線性的,沒法分理出區間範圍
  • 使用數組查詢的狀況 ---超過10個值須要判斷 ---條件對應的結果使單一值,而不是一系列操做

###快速循環 在JavaScript中,循環是致使性能問題的常見緣由,因此下面從以下幾個方面進行優化循環

####將循環次數存放在變量中

var value = [1,2,3,4,5];
var len = value.length;
for(var i=0;i<len;i++){
  //do something
}

####轉換行爲的方式 將上面的代碼改寫成以下所示:

var value = [1,2,3,4,5];
  var len = value.length;
  for(var i = len;i--;){
     //do something
  }

由於結束條件變爲與0進行比較,因此每一個循環的速度更快了。此時,for,while,do-while的速度都是差很少的

####避免for-in循環 for循環的另外一宗變化是for-in循環,它是用來遍歷javascript對象的可枚舉屬性的,典型的用法以下:

for(var prop in object){
     if(object.hasOwnProperty(prop)){
        // do something
     }
  }

for-in循環一般比其餘循環慢,由於它須要從一個特定的對象中解析每一個可枚舉屬性,反過來講,這意味着它爲了提取這些屬性須要檢查對象的原型和整個原型鏈。遍歷原型鏈就像遍歷做用鏈域,他會增長好事,從而下降整個循環的性能

###避免運行過長的腳本

###謹慎使用HTMLCollection對象 每次存取這類對象的屬性,都會從新查詢DOM中匹配的節點,爲了不這種昂貴的開銷,只有在必要時才存取HTMLCollection對象,並將常常存取的值存儲在局部變量中

相關文章
相關標籤/搜索