1. 引言
在上一篇文章《如何確保JavaScript的執行順序 - 之實戰篇》中,我們發現jQuery.html函數在動態載入跨域JavaScript時,在Firefox和Opera中可以按照引入順序執行,而在IE,Chrome和Safari中都不能確保執行順序。
經過分析,我們發現jQuery.html在處理跨域靜態JS檔案時,並非採用的同步AJAX(也存在同源策略的限制),而是在head中添加script標籤來完成的。
我們先來簡單回顧下HTML原始碼(test2_1.htm):
<html>
<head>
<title></title>
<script src="js/jquery-1.4.4.js" type="text/javascript"></script>
<script>
$(function(){
$('#container').html('<script src="http://test1.sanshi.me/jsorder/service.ashx?file=js/jquery-ui.js&delay=2000" type="text\/javascript"><\/script>' + '<script>alert(typeof(jQuery.ui));<\/script>');
});
</script>
</head>
<body>
<div id="container">
</div>
</body>
</html>
在實際測試中,我發現如果使用jQuery1.5.1,那麼得到的結果和使用jQuery1.4.4有些不同,請看下錶:
|
test2_1.htm(jquery-1.4.4.js) 通過jQuery.html動態載入跨域JavaScript檔案 |
test2_2.htm(jquery-1.5.1.js) 通過jQuery.html動態載入跨域JavaScript檔案 |
Firefox 3.6 |
|
|
IE 8 |
|
|
Chrome 10 |
|
|
Safari 4 |
|
|
Opera 11 |
|
|
2. jQuery1.5.1/1.4.4在Firefox上不一致行為
從上表我們明顯看出區別,jQuery1.5.1和1.4.4在處理動態載入跨域JS檔案時,只在Firefox上的行為不一致,這是為什麼呢?
深入代碼,經過調試我們把焦點放在jQuery1.4.4的第5859行,以及jQuery1.5.1的第7135行:
從上面代碼中,我們能看到的一個明顯區別是在jQuery1.5.1的第7149行多了這麼一行代碼:
script.async = “async”;
為script標籤添加一個名和值都為async的屬性,這是啥情況?Google之。。。。。。
3. script標籤的async屬性
相關文檔:
a) Script async, Raindrop and Firefox 3.6
b) Mozilla script document
c) Browser support for <script async=“true” />?
d) HTML5 async specification
總的說來,async是HTML5中為script標籤定義的屬性,目前只有Firefox3.6以上版本的瀏覽器才支援。
4. script標籤的async和defer屬性的區別
從上面的W3C的官方描述中,我們有如下結論:
1. async屬性和defer屬性都是用來標識指令碼的執行方式。
2. 對於內聯JavaScript(沒有src屬性),不能指定async和defer屬性
3. 設定async,不設定defer。指令碼將會非同步執行,也就是在指令碼下載完成後立即執行。
4. 不設定async,設定defer。指令碼將會在頁面DOM解析完畢後執行。
5. 兩個都不設定。指令碼的下載和執行是阻塞模式,將會阻塞DOM樹的繼續渲染。
目前,據我所知:Firefox3.6中script標籤支援async,不支援defer;而IE下,script標籤支援defer而不支援async屬性。
其實上面已經提到了async和defer的一個重要區別。async標識非同步執行(也就是說執行時可能頁面的DOM樹還沒有解析完成),而defer是在頁面的DOM樹解析完畢後執行。defer的這種特性和我們把JavaScript指令碼放在頁面的最底部的效果其實是一致的。
這點在Yahoo的“Best Practices for Speeding Up Your Web Site”的“Put Scripts at the Bottom”一節有詳細的描述:
5. 後記
至此,這個系列的文章全部完成。我把全部DEMO的原始碼打包供大家下載測試。如果你有什麼建議或意見,也歡迎光臨我的技術部落格,評論留念。