前面的章節皆在探討 JavaScript 核心,與執行環境無關;本篇則著重於 browser 上的相關 pattern。
Separation of Concerns 
Concerns 有三:
Context:文件內容,即 HTML 
Presentation:外觀表現,即 CSS 
Behavior:使用者互動或文件動態改變,即 JavaScript 
 
 
當關閉 CSS 或 JavaScript 時,應確保頁面仍可正常閱讀,且主要功能仍可正常運作 
避免將 CSS 或 JavaScript 內嵌在 context 中 
應直接檢測明確的 method 或 property,避免使用 user agent sniffing 
 
DOM Scripting 
避免在 loop 中存取 DOM,應 assign 其 reference 給 local variable 
盡量使用 selector API(如 document.querySelector() 或 document.querySelectorAll()),而 id="" 是尋找節點最快的方式(document.getElementById()) 
更新 DOM 會使 browser 進行 repain(重新繪製畫面)及 reflow(重新計算元素的幾何結構),因此應在 “live” DOM tree 之外進行操作(如:新增時先用 document fragment 容納所有節點,待一連串的動作完成後再將這個已定案的 fragment 加至 DOM;修改時則可先在 clone 中處理,完成後再替換原本的節點) 
 
Events 
使用 addEventListener()/attachEvent() 時,適時加上 stopPropagation()/cancelBubble=true 及 preventDefault()/returnValue=false 
利用 event delegation 減少 event listeners 的總量(如 div 內有十個 button,可在 div 上加一個 listener 就好而不是在每一個 button 都加) 
 
Long-Running Scripts 
JavaScript 中雖沒有 thread,但可藉由 setTimeOut() 模擬,或使用較新的 browser 所支援的 Web Workers,以避免因 lag 而使 user 不能操作畫面 
 
Remote Scripting 
XMLHttpRequest (AJAX) 
JSONP (for cross-domain) 
iframe 
image beacon(只需送 request 不需接 response 時可用,response 傳 HTTP 204 為佳) 
 
Deploying JavaScript 
合併 scripts 以減少 HTTP request,可用 cat 命令操作 
使用 minify 工具壓縮,縮小檔案大小 
開啟 gzip 壓縮,增快載入速度 
 
.htaccess 1
AddOutputFilterByType  DEFLATE text/html text/css text/plain text/xml application/javascript application/json
 
使用 Expires header,增加檔案待在 cache 的機會 
 
.htaccess 1
2
ExpiresActive  On 
ExpiresByType  application/x-javascript "access plus 10 years" 
 
Loading Strategies 
<script> 的 attribute 不要加上 language 或 type 等歷史遺跡,可加 defer 或 HTML5 的 async 使其不會 block 網頁的下載流程(browser 會同時下載多個檔案,但遇到外部 script 會暫停下一步下載直到該 script 完成下載並分析與執行完畢);async 尚未廣泛支援,因此可將外部 script 放置頁面底端(</body> 前),或動態加入 <script> 元素實現 asyncronous 下載(document.createElement("script")),後者需注意各 script 檔之間的相依性(因各檔案下載完成的時機未必如同預期順序) 
當頁面需在 server-side 進行複雜運算時,可使用 chunked encoding 分批傳送頁面片段,利用 server 尚未完成工作時先將部分靜態內容送給 client-side 
 
Strategy of Loading a Big Script 
lazy loading:先載入 core 使主要功能開始運作,再用 onload 動態加 <script> 載入其他次要功能(如特效、XHR 實作等) 
loading on demand:需要時才載入,並在完成後執行 callback 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require ("extra.js" , function  ()   {
		functionDefinedInExtraJS();
});
function  require (file, callback)   {
		var  script = document .getElementsByTagName('script' )[0 ],
		newjs = document .createElement('script' );
		
		newjs.onreadystatechange = function  ()   {
				if  (newjs.readyState === 'loaded'  || newjs.readyState === 'complete' ) {
						newjs.onreadystatechange = null ;
						callback();
				}
		};
		
		newjs.onload = function  ()   {
				callback();
		};
		newjs.src = file;
		script.parentNode.insertBefore(newjs, script);
}
 
preloading:若希望單純只下載 script 檔案而不進行分析及執行,IE 可用 image beacon,其他 browser 可用 <object> 替代 <script>