前端優化的目的是什麼 ?javascript
1. 從用戶角度而言,優化可以讓頁面加載得更快、對用戶的操做響應得更及時,可以給用戶提供更爲友好的體驗。html
2. 從服務商角度而言,優化可以減小頁面請求數、或者減少請求所佔帶寬,可以節省可觀的資源。前端
1、頁面級優化
1. 減小 HTTP請求數java
(1). 從設計實現層面簡化頁面正則表達式
1. Javascript
(1). DOM
DOM操做應該是腳本中最耗性能的一類操做,例如增長、修改、刪除 DOM元素或者對 DOM集合進行操做。若是腳本中包含了大量的 DOM操做則須要注意如下幾點:
a. HTML Collection(HTML收集器,返回的是一個數組內容信息)
在腳本中 document.images、document.forms 、getElementsByTagName()返回的都是 HTMLCollection類型的集合,在平時使用的時候大多將它做爲數組來使用,由於它有 length屬性,也可使用索引訪問每個元素。不過在訪問性能上則比數組要差不少,緣由是這個集合並非一個靜態的結果,它表示的僅僅是一個特定的查詢,每次訪問該集合時都會從新執行這個查詢從而更新查詢結果。所謂的 「訪問集合」 包括讀取集合的 length屬性、訪問集合中的元素。
所以,當你須要遍歷 HTML Collection的時候,儘可能將它轉爲數組後再訪問,以提升性能。即便不轉換爲數組,也請儘量少的訪問它,例如在遍歷的時候能夠將 length屬性、成員保存到局部變量後再使用局部變量。
b. Reflow & Repaint
除了上面一點以外, DOM操做還須要考慮瀏覽器的 Reflow和Repaint ,由於這些都是須要消耗資源的,具體的能夠參加如下文章:
如何減小瀏覽器的repaint和reflow?
Understanding Internet Explorer Rendering Behaviour
Notes on HTML Reflow數組
(2). 慎用 with
with(obj){ p = 1}; 代碼塊的行爲其實是修改了代碼塊中的 執行環境 ,將obj放在了其做用域鏈的最前端,在 with代碼塊中訪問非局部變量是都是先從 obj上開始查找,若是沒有再依次按做用域鏈向上查找,所以使用 with至關於增長了做用域鏈長度。而每次查找做用域鏈都是要消耗時間的,過長的做用域鏈會致使查找性能降低。
所以,除非你能確定在 with代碼中只訪問 obj中的屬性,不然慎用 with,替代的可使用局部變量緩存須要訪問的屬性。
(3). 避免使用 eval和 Function
每次 eval 或 Function 構造函數做用於字符串表示的源代碼時,腳本引擎都須要將源代碼轉換成可執行代碼。這是很消耗資源的操做 —— 一般比簡單的函數調用慢 100倍以上。
eval 函數效率特別低,因爲事先沒法知曉傳給 eval 的字符串中的內容,eval在其上下文中解釋要處理的代碼,也就是說編譯器沒法優化上下文,所以只能有瀏覽器在運行時解釋代碼。這對性能影響很大。
Function 構造函數比 eval略好,由於使用此代碼不會影響周圍代碼 ;但其速度仍很慢。
此外,使用 eval和 Function也不利於Javascript 壓縮工具執行壓縮。
(4). 減小做用域鏈查找(這方面設計到一些內容的相關問題)
前文談到了做用域鏈查找問題,這一點在循環中是尤爲須要注意的問題。若是在循環中須要訪問非本做用域下的變量時請在遍歷以前用局部變量緩存該變量,並在遍歷結束後再重寫那個變量,這一點對全局變量尤爲重要,由於全局變量處於做用域鏈的最頂端,訪問時的查找次數是最多的。
低效率的寫法:
// 全局變量
var globalVar = 1;
function myCallback(info){
for( var i = 100000; i--;){
//每次訪問 globalVar 都須要查找到做用域鏈最頂端,本例中須要訪問 100000 次
globalVar += i;
}
}
更高效的寫法:
// 全局變量
var globalVar = 1;
function myCallback(info){
//局部變量緩存全局變量
var localVar = globalVar;
for( var i = 100000; i--;){
//訪問局部變量是最快的
localVar += i;
}
//本例中只須要訪問 2次全局變量
在函數中只須要將 globalVar中內容的值賦給localVar 中區
globalVar = localVar;
}
此外,要減小做用域鏈查找還應該減小閉包的使用。
(5). 數據訪問
Javascript中的數據訪問包括直接量 (字符串、正則表達式 )、變量、對象屬性以及數組,其中對直接量和局部變量的訪問是最快的,對對象屬性以及數組的訪問須要更大的開銷。當出現如下狀況時,建議將數據放入局部變量:
a. 對任何對象屬性的訪問超過 1次
b. 對任何數組成員的訪問次數超過 1次
另外,還應當儘量的減小對對象以及數組深度查找。
(6). 字符串拼接
在 Javascript中使用"+" 號來拼接字符串效率是比較低的,由於每次運行都會開闢新的內存並生成新的字符串變量,而後將拼接結果賦值給新變量。與之相比更爲高效的作法是使用數組的 join方法,即將須要拼接的字符串放在數組中最後調用其 join方法獲得結果。不過因爲使用數組也有必定的開銷,所以當須要拼接的字符串較多的時候能夠考慮用此方法。瀏覽器
關於 Javascript優化的更詳細介紹請參考:
Write Efficient Javascript(PPT)
Efficient JavaScript
2. CSS選擇符
在大多數人的觀念中,都以爲瀏覽器對 CSS選擇符的解析式從左往右進行的,例如
#toc A { color: #444; }
這樣一個選擇符,若是是從右往左解析則效率會很高,由於第一個 ID選擇基本上就把查找的範圍限定了,但實際上瀏覽器對選擇符的解析是從右往左進行的。如上面的選擇符,瀏覽器必須遍歷查找每個 A標籤的祖先節點,效率並不像以前想象的那樣高。根據瀏覽器的這一行爲特色,在寫選擇符的時候須要注意不少事項,有人已經一一列舉了, 詳情參考此處。緩存
3. HTML
對 HTML自己的優化現現在也愈來愈多的受人關注了,詳情能夠參見這篇 總結性文章 。服務器