幾個首要特性:
- script標簽(不帶
defer
或async
屬性)的會阻止文檔渲染。相關腳本會立即下載並執行。 document.currentScript
可以獲得當前正在運行的腳本(Chrome 29+, FF4+)- 腳本順序再默認情況下和script標簽出現的順序一致
有defer
或async
屬性(defer和
async沒有完全兼容所有瀏覽器
)
- 僅有async屬性,腳本會異步執行
- 僅有defer屬性,腳本會在文檔解析完畢后執行
- 兩個屬性都沒有,腳本會被同步下載並執行(順序下載,順序執行),期間會阻塞文檔解析
如下示例A1,A2,A3
<!-- HTML code --> <script src="https://snipt.net/raw/A1_7b08744009c450e07c0bfc1d606fc72e/"></script> <script src="https://snipt.net/raw/A2_a2e8c05c1f6fc0e47d259aa899304e89/"></script> <script src="https://snipt.net/raw/A3_4fab3017d3d46cbfc4bbd88aab006650/"></script>
當第二個文件A2的尺寸遠大於另外兩個文件,A1下載執行不受影響,A3在A2下載執行完成之后下載
另外,當<script>標簽下載執行過程中,document.ready事件等待所有<script>內容下載完成后才能被觸發;
優化方案
一:異步加載腳本
setTimeout(function(){ var s = document.createElement('script'); s.src = "/will-not-stop-loading.js"; document.body.appendChild(s); });
setTimeout
未指定第二個參數(延遲時間),會立即執行第一個參數傳入的函數。 但是JavaScript引擎會將該函數插入到執行隊列的末尾。 這意味着正在進行的DOM渲染過程完全結束后(此時瀏覽器忙提示當然會消失),才會調用上述函數
二:load事件(推薦)
$(window).load(function(){ $('script[type="text/async-script"]').each(function(idx, el){ var $script = $('<script>'); if(el.dataset.src) $script.attr('src', el.dataset.src); else $script.html(el.text); $script.appendTo('body'); el.remove(); }); });
- 對於外部
<script>
,生成一個新的包含正確src
的<script>
。 - 對於行內
<script>
,生成一個新的包含正確內容的<script>
,type
默認即為"application/javascript"
。
該方法采用DOM中<script>
加載的方式,沒有AJAX+Eval改變腳本中當前路徑的缺點。 http://harttleland.com中的Google Analytics、MathJax等腳本都采用這種處理方式
另外一種寫法
<script type="text/javascript"> // 加載較慢會阻塞頁面渲染的腳本 function loadComplete(){ var hm1 = document.createElement("script"); hm1.src = "./secondLoad.js"; var hm2 = document.createElement("script"); hm2.src = "./thirdLoad.js"; document.body.appendChild(hm1) hm1.onload = function(){ document.body.appendChild(hm2) } } </script> <!-- 加載最快且優先級最高的腳本 --> <script type=text/javascript onload='loadComplete()' src='./firstAndFastLoad.js'></script>
三:document.write()會把輸出寫入到腳本文檔所在的位置,瀏覽器解析完documemt.write()所在文檔內容后,繼續解析document.write()輸出的內容,
然后在繼續解析HTML文檔
<script type="text/javascript">//<![CDATA[ document.write('<script type="text/javascript" src="test.js"><//script>'); document.write('<script type="text/javascript">'); document.write('alert(2);') document.write('alert("我是" + tmpStr);'); document.write('<//script>'); //]]> </script>