----------------------------------------------------------- 第一章 加載和執行 -------------------------------------
1.腳本位置
瀏覽器在遇到<script>標籤時會等待腳本下載完並執行完纔會繼續渲染頁面
由於js代碼有可能會改變dom結構,因此須要等待js的執行完成
遇到<script>標籤 -> 下載腳本 -> 執行腳本 -> 繼續渲染
舊瀏覽器:逐個下載,逐個執行
新瀏覽器:併發下載,順序逐個執行
so: 腳本儘可能放在靠近</body>的底部
儘量合併腳本(下載一個比下載多個快)
2.延遲的腳本
defer:馬上下載,等到onload事件被觸發前才執行(僅IE4.0+和Firefox3.5+支持)
動態建立<script>節點:添加到頁面時開始下載,下載完成馬上執行
* 下載完成的事件:readystatechange(IE)、onload(其餘瀏覽器)
XHR腳本注入:XMLHttpRequest來獲取js文件內容,再動態建立<script>節點
* 必須處於相同域,不適用大型Web應用
3.推薦的方式
先添加動態加載所需的代碼,而後加載其餘代碼:
<script type="text/javascript" src = "loader.js"></script>
<script type="text/javascript">
loadScript("the-rest.js"),function(){
Application.init();
}
</script>
放置</body>閉合標籤前,保證DOM結構已經建立完畢,無需其餘的時間,例如window.onload來檢測頁面是否準備好
4.類庫
LazyLoad.js:
<script type="text/javascript" src = "lazyload-min.js"></script>
<script type="text/javascript">
LazyLoad.js(["first.js","second.js"]),function(){
Application.init();
}
</script>
lab.js:
<script type="text/javascript" src = "lab.js"></script>
<script type="text/javascript">
$LAB.script("first.js").wait() // 若是須要按序執行則須要加上wait()
.script("second.js")
.wait(function(){
Application.init();
});
</script>
--------------------------------第二章 數據訪問---------------------------------------
1.做用域鏈和標識符解析
內部屬性[[Scope]] --- 做用域鏈 --- 0 --- 活動對象([[Scope]]屬性中所包含的對象,即函數範圍內的變量)
--- 1 --- 全局對象(this, window, document 等等全局變量)
2.so 儘可能把鏈深處的變量存儲到局部變量裏,介以提高性能
* 採用優化過的js引擎不存在這種問題,老版的IE、Firefox和Safari都有問題javascript
3.改變做用域鏈:
with(document){...} //with把document推動了做用域鏈的第一層,可是致使訪問局部變量路徑變遠了,因此不推薦
try{}catch(ex){} //catch裏面把異常對象推入了做用域鏈的頭部html
4.訪問對象也同樣,首先在實例中查找,而後再去原型鏈中查找
so 若是須要訪問屢次,那麼緩存對象屬性能夠提高性能
--------------------------------第三章 DOM編程---------------------------------------
1.儘可能少訪問DOM,把運算留在ECMAScript這一端處理java
2.innerHTML屬性和相似document.createElement()、document.createTextNode()的原生DOM方法性能差很少正則表達式
3.cloneNode()比createElement要稍快一點算法
4.HTML集合
document.getElementsByName();
document.getElementsByClassName();
document.getElementsByTagName();
HTML集合是動態的,類數組,提供一個length屬性
* 訪問length屬性時會從新執行一次查詢的過程
so,緩存length屬性頗有必要
5.只返回元素節點
children childNodes
childElementCount childNodes.length
firstElementChild firstChild
lastElementChild lastChild
nextElementSibling nextSibling
previousElementSibling previousSibling
6.選擇器API
原生DOM方法:querySelectorAll();
7.重繪與重排
構建DOM樹與渲染樹 --- 繪製頁面元素
重排:
添加、刪除DOM元素
元素位置改變
元素尺寸改變
內容改變(例如文本改變、圖片被另一個不一樣尺寸的圖片替代)
頁面渲染器初始化
瀏覽器窗口尺寸改變
瀏覽器經過隊列化修改並批量執行來優化重排過程,但如下屬性會強制刷新隊列:
offsetTop, offsetLeft, offsetWidth, offsetHeight
scroll...
client...
getComputedStyle()(currentStyle in IE)
以上屬性須要返回最新的佈局信息,因此瀏覽器須要執行隊列中的"待處理變化"並觸發重排以返回正確的值
so 以上屬性儘可能少使用,而且使用這些屬性的位置應該在修改佈局信息的後面,中間的話會致使屢次重排編程
8.最小化重繪和重排
·合併屢次全部的改變一次處理
·批量修改DOM
脫離文檔流
應用多重改變
帶回文檔
三種方式:隱藏元素 --- 修改 --- 從新顯示
使用文檔片斷(document fragment)
拷貝 --- 修改拷貝 --- 替換原始(replaceChild(new, old))
9.緩存佈局信息windows
10.讓元素脫離動畫流
絕對定位頁面上的動畫元素,將其脫離文檔流
讓元素動起來,只重繪了該元素,會臨時覆蓋部分頁面
動畫結束時恢復定位,只下移一次文檔的其餘元素跨域
11.元素不少時應避免使用:hover這個CSS僞選擇器數組
12.事件委託
只綁定最外圍的元素點擊事件,判斷來源是不是目標瀏覽器
--------------------------------第四章 算法和流程控制---------------------------------------
1.for-in循環的性能只有其餘循環的1/7,
so 儘可能不要使用for-in來遍歷對象的屬性名
2.少許條件用if-else, 大量條件用switch-case
3.列表查找比循環查找要快
so, 數據放置一個Array中, 經過位置來查找
4.儘可能減小循環
5.存在重複的計算結果時,可使用緩存
--------------------------------第五章 字符串和正則表達式---------------------------------------
1.字符串鏈接
把基礎字符串及放置左邊能夠提高性能
* 由於除IE外,其餘瀏覽器會嘗試爲左側的字符串分配更多的內存,而後簡單地將第二個字符串拷貝至它的末尾
2.Array.prototype.join();
String.prototype.concat(); //concat比普通的+和+=以及join慢一點
3.正則表達式的編譯很快,只須要注意別在循環中重複編譯正則表達式就行
while(/regex1/.test(str1))
4.只是檢測位置不適用正則表達式
例如檢測是否以;結尾:
/;$/ --- str.charAt(str.length-1)== ";";
其餘函數有slice、substr、substring、indexOf和lastIndexOf
5.去除首尾空格
用兩個子表達式綜合效率要高一些,尤爲是在處理長字符串時
str.replace(/^\s+/,"").replace(/\s+$/,"");
* 其餘有一次性處理完的,但多少有各方面的性能問題
比方說/^\s+|\s+$/,每一個字符串都會去匹配這兩個分支條件
--------------------------------第六章 快速響應的用戶界面---------------------------------------
1.js的執行不該超過100毫秒(用戶體驗中能忍受的頁面阻塞時間最大值)
2.定時器的推薦最小值爲25毫秒
* windows系統的最小識別爲15毫秒,設置一個小於15毫秒的定時值,IE會鎖定
* 在小於10毫秒時,各瀏覽器各系統均會有不一樣的表現
3.能夠經過定時器來依次執行多個任務
* 將一個任務分割成多個任務,用定時器來執行
4.Web Workers
Worker沒有綁定UI線程,適用於純數據處理,與網頁代碼經過事件接口進行通訊
網頁代碼:
var worker = new Worker("code.js");
worker.onmessage = faunction(event){
// ...
}
worker.postMessage("Thyiad");
worker代碼(code.js):
importScripts("file1.js", "file2.js");
self.onmessage = function(event){
self.postMessage("Hello, " + event.data + "!");
}
--------------------------------第七章 AJAX---------------------------------------
1.經常使用的三種技術是:XHR、動態腳本注入和multipart XHR
2.XHR
readyState的值
3 正在與服務器交互
4 整個響應已接收完畢,可進行操做
* GET經常使用來請求數據,POST則用來發送數據
一個GET請求只會發送一次數據包,而一個POST請求會發送兩次數據包(一個裝載頭一個裝載正文)
應該在參數接近或超過2048個字符時,才應該使用POST獲取數據,由於IE限制URL長度
* 不能跨域請求數據
3.動態腳本注入
動態建立一個script元素,設置src屬性爲不一樣域的URL
* 返回的響應消息必須是可執行的JavaScript代碼
4.Multipart XHR
一次請求多個資源,從readyState值爲3時開始設定一個定時器監聽處理數據(須要本身定義數據格式並處理)
* 這種方式資源不會被緩存
* IE六、7不支持readyState爲3的狀態和data:URL
5.Beancons - 信標
經過建立一個Image,設定src來回傳數據
var beacon = new Image();
beacon.src=url+'?'+params.join('&');
beancon.onload = function(){ // 經過監聽image的load事件來處理簡單返回時間
if(this.width === 1){ // 若是不須要返回數據,那麼響應中應該發送一個 204 No Content 狀態碼(即:不帶消息正文)
} // 以阻止客戶端繼續等待永遠不會到來的消息正文
else{}
}
6.數據格式
XML 不推薦,數據量大解析又慢
JSON 推薦,數據輕便解析又快
JSON-P 返回的文本做爲js代碼直接執行(用eval直接調用)
HTML 不推薦,既緩慢又臃腫
自定義 同JSON,適用的情景下速度還會比JSON更快點
7.緩存數據
用GET請求數據、響應中發送 Expires 頭信息:Expires: Mon, 28 Jul 2015 23:30:00 GMT // 告訴瀏覽器緩存此響應到7月
本地數據存儲:使用對象的屬性存儲緩存(鍵存url,值存返回數據)
* 本地存儲最適用移動設備,大多移動設備的瀏覽器都很小或沒有緩存
--------------------------------第八章 編程實踐---------------------------------------
1.避免雙重求值
儘可能不使用eval和Function構造函數,以免雙重求值帶來的性能消耗
一樣的,應該給setTimeout()和setInterval()傳入函數而不是字符串做爲參數
2.使用直接量建立對象和數組 - 效率更高
3.不要重複工做
當須要檢測瀏覽器時,可以使用延遲加載或條件預加載
延遲加載:
function addHandler(target, eventType, handler){
if(target.addEventListener){
addHandler = function(target, eventType, handler){
target.addEventListener(eventType, handler, false);
}
}
else{
addHandler = function(target, eventType, handler){
target.attachEvent("on"+eventType, handler);
}
}
addHandler(target, eventType, handler);
}
條件預加載:
var addHandler = document.body.addEventListener ?
function(target, eventType, handler){
target.addEventListener(eventType, handler, false);
} :
function(target, eventType, handler){
target.attachEvent("on"+eventType, handler);
};
4.使用速度快的部分
位操做
toString()方法把數字轉換爲二進制形式的字符串:
var num = 25;
alert(num.toString(2)); //"11001"
是否爲2的整數:
var num = 25;
if(num & 1){ // 奇數&1 => 1
}
else{} // 偶數
位掩碼:
var OPTION_A = 1, OPTION_B = 2, OPTION_C = 4, OPTION_D = 8, OPTION_E = 16;
var options = OPTION_A | OPTION_C | OPTION_D;
if(options & OPTION_A){ //選項A是否在列表中
// ...
}
5.原生方法
儘可能使用原生方法,好比數學計算(Math)和CSS選擇器(querySelector()、querySelectorAll())
--------------------------------第九章 構建並部署高性能JavaScript應用---------------------------------------
1.Apache Ant
2.合併多個JavaScript文件
3.預處理JavaScript文件
在js代碼中添加宏定義(#define, #undef)和條件編譯(#if, #ifdef, #ifndef)
4.JavaScript壓縮
JSMin http://www.crockford.com/javascript/jsmin.html
YUI Compressor http://developer.yahoo.com/yui/compressor
Closure Compiler http://code.google.com/closure/compiler/
Packer http://dean.edwards.name/packer/
5.JavaScript的HTTP壓縮
Accept-Encoding HTTP頭:值爲gzip、compress、deflate和identity
服務器會選擇最合適的編碼方法,經過Content-Encoding HTTP頭來告知瀏覽器
6.緩存JavaScript文件
* Expires HTTP 響應頭
* 客戶端存儲機制(js本身控制)
* HTML5 離線應用緩存(manifest屬性,mime type爲text/cache-manifest)
7.處理緩存問題
推薦使用時間戳後綴
8.CDN
--------------------------------第十章 工具---------------------------------------
1.原生分析
new Date(); //經過Date相減
2.YUI Profiler
3.FireBug
4.Console API profile()、profileEnd() console.profile("regexTest"); regexTest(); console.profileEnd(); * profileEnd()會阻塞後續執行,因此能夠將profileEnd()調用封裝在setTimeout中 5.Page Speed 對如何重構進行分析建議,好比哪些腳本在load以前沒有用到過,能夠延遲加載 * FireBug插件 6.Fiddler HTTP調試代理工具,整個網絡過程的Timeline進行分析,哪塊佔用時間多須要優化 7.YSlow 分析後的優化建議工具 * FireBug插件 8.dynatrace Ajax Edition 同Fiddler的做用,能夠監控整個過程的時間,更能深刻到特定的事件