##《高性能網站建設進階指南》知識摘錄 現在,許多網站和項目的整個用戶界面都是用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語句塊,這樣就能夠像訪問局部變量同樣訪問name
和age
屬性了。實際上它是將一個新的變量對象添加到執行上下文做用域的頂部 函數
這樣你在訪問內部變量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.count
筆data.item.count
快
###快速條件判斷 在條件有不少的狀況下,究竟是使用if-else
仍是switch
,if-else
和switch
的結構相信你們都已經很熟悉了,在這裏我就再也不贅述了,下面還提供一種方法,數組查詢方法
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對象,並將常常存取的值存儲在局部變量中