平時最常使用的就是這種同步載入形式: <script src="http://yourdomain.com/script.js"></script> 同步模式,又稱阻塞模式,會阻止瀏覽器的後續處理,停止了後續的解析,因此停止了後續的檔案載入(像)、渲染、代碼執行。 js 之所以要同步執行,是因為 js 中可能有輸出 document 內容、修改dom、重新導向等行為,所以預設同步執行才是安全的。 以前的一般建議是把<script>放在頁面末尾</body>之前,這樣儘可能減少這種阻塞行為,而先讓頁面展示出來。 簡單說:載入的網路 timeline 是瀑布模型,而非同步載入的 timeline 是並行存取模型。 常見非同步載入(Script DOM Element) [javascript] (function() { var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://yourdomain.com/script.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); })(); 例如 Google Analytics 和 Google+ Badge 都使用了這種非同步載入代碼: [javascript] (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); (function() {var po = document.createElement("script"); po.type = "text/javascript"; po.async = true;po.src = "https://apis.google.com/js/plusone.js"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(po, s); })(); 百度地圖的非同步載入: [javascript] var map; //全域地圖 function initialize() { map = new BMap.Map('map'); var point = new BMap.Point(121.491, 31.233); map.centerAndZoom(point, 11); //使用滑鼠滾輪控制縮放 map.enableScrollWheelZoom(); //添加地圖控制項 map.addControl(new BMap.NavigationControl()); map.addControl(new BMap.ScaleControl()); map.addControl(new BMap.OverviewMapControl()); map.addControl(new BMap.MapTypeControl()); //點擊地圖就添加標註點 map.addEventListener("click", addMarkerService); PanOptions.noAnimation=false; } function loadScript() { var script = document.createElement("script"); script.src = "http://api.map.baidu.com/api?v=1.5&ak=imORpY5Kv1BDZpM4ab4QPQM5&callback=initialize"; //此為v1.5版本的引用方式 // http://api.map.baidu.com/api?v=1.5&ak=您的密鑰&callback=initialize"; //此為v1.4版本及以前版本的引用方式 document.body.appendChild(script); } window.onload = loadScript; 但是,這種載入方式在載入執行完之前會阻止 onload 事件的觸發,而現在很多頁面的代碼都在 onload 時還要執行額外的渲染工作等,所以還是會阻塞部分頁面的初始化處理。 [javascript] (function() { function async_load(){ var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://yourdomain.com/script.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); } if (window.attachEvent) window.attachEvent('onload', async_load); else window.addEventListener('load', async_load, false); })(); 這和前面的方式差不多,但關鍵是它不是立即開始非同步載入 js ,而是在 onload 時才開始非同步載入。這樣就解決了阻塞 onload 事件觸發的問題。 補充:DOMContentLoaded 與 OnLoad 事件 DOMContentLoaded : 頁面(document)已經解析完成,頁面中的dom元素已經可用。但是頁面中引用的圖片、subframe可能還沒有載入完。 OnLoad:頁面的所有資源都載入完畢(包括圖片)。瀏覽器的載入進度在這時才停止。 這兩個時間點將頁面載入的timeline分成了三個階段。 非同步載入的其它方法 由於Javascript的動態特性,還有很多非同步載入方法: XHR Eval XHR Injection Script in Iframe Script Defer document.write Script Tag 還有一種方法是用 setTimeout 延遲0秒 與 其它方法組合。 XHR Eval :通過 ajax 擷取js的內容,然後 eval 執行。 var xhrObj = getXHRObject(); [javascript] xhrObj.onreadystatechange = function() { if ( xhrObj.readyState != 4 ) return; eval(xhrObj.responseText); }; xhrObj.open('GET', 'A.js', true); xhrObj.send('');