標籤:
javaScript 在瀏覽器中的運行效能,在web2.0時代顯得尤為重要,成千上萬行javaScript代碼無疑會成為效能殺手,
在較低版本的瀏覽器執行JavaScript代碼的時候,由於瀏覽器只使用單一進程來處理ui介面重新整理和JavaScript指令碼執行,
這意味著在載入javascript檔案的時候不能同時做任何其他的事情。 在載入的同時造成了使用者互動阻塞;
理論上來說,把樣式與行為有關的指令碼放在一起率先載入,這樣有利於確保正確的使用者體驗,例如下面的代碼:
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>javascript</title><script src="file.js" type="text/javascript" charset="utf-8"></script><script src="file1.js" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" type="text/css" href="file.css"/><link rel="stylesheet" type="text/css" href="file1.css"/><link rel="stylesheet" type="text/css" href="file2.css"/></head><body></body></html>
這種看似合理的代碼其實有著很嚴重的效能問題:在javascript檔案載入並執行完成之前會阻止頁面進行渲染,我們的web頁面會出現一片空白
無法與之正常互動,這稱之為指令碼阻塞
由於指令碼會阻塞頁面其他資源的載入 我們可以把所有的script標籤放在</body>之前 在頁面載入的最後來載入javascript檔案
<!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>javascript</title> <link rel="stylesheet" type="text/css" href="file.css"/> <link rel="stylesheet" type="text/css" href="file1.css"/> <link rel="stylesheet" type="text/css" href="file2.css"/></head><body> <!--推薦所有的js檔案位置--> <script src="file.js" type="text/javascript" charset="utf-8"></script> <script src="file1.js" type="text/javascript" charset="utf-8"></script></body></html>
-----------最佳化javascript的首要任務,將js檔案放置在頁面底部;
那如何建立一個無阻塞的指令碼呢?
無阻塞指令碼的秘訣在於,在頁面載入完成之後才開始載入javascript代碼。 我們要在window對象的load時間觸發後再下載並執行指令碼,
已知有很多種方式可以實現這一效果,這裡簡單例舉一二:
1.HTML5新特性
html5為script標籤提供了兩個新的屬性 一個是defer 另一個是async 它們採用的都是並行下載的方式; 在下載過程中並不會造成頁面阻塞
它們的區別在於 defer表示等待頁面載入完成才會執行,async則是它本身載入完成後就自動執行;
defer目前已被各大主流瀏覽器所相容;
2.建立動態指令碼元素;這很容易使頁面渲染完成之後再進行指令碼載入;
例如:
<!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>javascript</title> </head><body> <script type="text/javascript"> var script = document.createElement("script"); script.src = "ztf.js"; document.getElementsByTagName("head")[0].appendChild(script); </script></body></html>
我們使用標準的dom方法document.createElement來動態建立一個script元素並指定它的src;這行成了一個動態指令碼模式;在任意時刻插入任意的javascript代碼都會被瀏覽器執行;(建立的script最好不要插入到body裡面;這樣可能會引起ie拋出一個‘操作已終止’的錯誤資訊;)
ff,opera,chrome和safari3以上版本的script標籤會在載入完成觸發onload事件。
而在老版本ie下(ie6-10) 它會觸發一個readystatechange事件。<script>元素會提供一個readyState屬性,它的值在scr載入不同過程產生不同的變化;我們通常會使用到 "loaded" 和 "complete"。
通過“用戶端能力檢測” (http://www.jxbh.cn/newshow.asp?id=1434&tag=2) 我們可以建立一個通用的動態載入javascript的函數:
function loadScript(url,callback){ var script = document.createElement("script"); script.type="text/javascript"; if(script.readyState){ //用戶端能力檢測 如果支援readyState則返回的是字串 反之返回undefined script.onreadystatechange = function(){ //onreadystatechange事件 if(script.readyState=="loaden"||script.readyState=="complete"){ script.onreadystatechange=null; callback(); } } }else{ script.onload = function(){ callback(); } } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }
這個函數接受兩個參數;javascript檔案的url和完成載入後的回呼函數。loadScript()函數的用法如下
loadScript("ztf.js",function(){ alert("loadend")});
如果需要的話,你可以儘可能多的載入javascript檔案到頁面上,但一定要考慮清楚檔案的載入順序,可以不斷的使用callback回呼函數載入多個javascript指令碼;
另外還有一種,ajax動態請求載入指令碼 在這裡筆者就不一 一說明 ,大家查閱有關文檔;
部分內容摘自《高效能javascript》
javascript效能最佳化:建立javascript無阻塞指令碼