1. JavaScript加載時間線(理論):
js本是單線程執行,瀏覽器爲幾個明顯的耗時任務單獨開闢線程解決耗時問題(也就是 異步)
時間線:瀏覽器在運行一個頁面時,首先會初始化js的功能,當初始化初試完js這一個功能後,也就是js開始發揮作用那一刻,開始記載着這一系列瀏覽器要發生的過程;
這一系列順序分爲十個步驟:
(1).創建 Document 對象,開始解析Web頁面;此階段狀態document.readyState = 'loading';
(2).遇到 link 外部 css 文件,創建線程加載,並繼續解析文檔(異步);
(3).遇到 script 外部 js 文件,並且沒有設置async、defer 的時候,瀏覽器加載並阻塞,等待 js 加載完成並執行改腳本,繼續解析文檔(異步時最好別用document.write(),容易出問題);
(4).遇到 script 外部 js 文件,並且有設置async、defer的時候,瀏覽器創建線程加載,並繼續解析文檔(異步);
(5).遇到 img 等,瀏覽器創建線程加載,並繼續解析文檔;
(6).當文檔解析完成,也就是DOM Tree加載完成時,此階段狀態document.readyState = 'interactive';
(7).接着,所有設置有 defer 的腳本會按照順序執行;
(8).document 對象觸發DOMContentLoaded事件,這也標誌着程序執行從同步腳步執行階段,轉化爲事件驅動階段
(9).當所有async的腳本加載完成並執行後,img等加載完成後,此階段狀態爲document.readyStste = 'complete',window對象觸發load事件;
(10).從此,以異步響應方式處理用戶輸入,網絡事件等
2.異步的加載:
(1).同步模式,又稱阻塞模式,會阻止瀏覽器的後續處理,停止後續的解析,只有噹噹前加載完成,才能進行下一步操作。所以默認同步執行纔是安全的。但這樣如果js中有輸出document內容、修改dom、重定向等行爲,就會造成頁面堵塞。所以一般建議把<script>標籤放在<body>結尾處,這樣儘可能減少頁面阻塞
(2).異步加載又叫非阻塞加載,瀏覽器在下載執行js的同時,還會繼續進行後續頁面的處理,不會造成頁面阻塞;
(3).異步加載的方式一:創建動態的script標籤
//第一種
(function(){
var att = document.createElement("script"); //創建script標籤
att.type = "text/javasctipt"; //添加類型
att.async = true; //true爲異步支持
att.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js"; //添加要放入的js文件
//第一種添加位置
var x = document.getElementsByTagName("head")[0];
x.insertBefore(att, x.firstChild); //將這個script標籤添加到head下面
//第二種添加位置
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(att, s); //將這個script標籤添加到第一個script標籤的之前
//第三種添加位置
document.head.appendChild(att) //添加到head下title標籤下面
})();
創建script標籤,插入到dom中,加載完畢執行回調函數
//第二種
function loadScript(url, callback){
var script = document.createElement('script');
script.type = "text/javascript";
//處理兼容性
if(script.readyState){ //IE9以下
script.onreadystatechange = function(){
if(script.readyState=='complete'||script.readyState=='loaded'){
callback();//obj[(callback)]()
}
}
}else{
script.onload = function () { //firefox chrome safair opera
callback();//obj[(callback)]()
}
}
script.src = url; //js文件路徑
document.head.appendChild(script);
}
loadScript(url,callback)
但是這種加載方式執行完之前會阻止onload事件的觸發,而現在很多頁面的代碼都在onload時還執行額外的渲染工作,所以還是會阻塞部分頁面的初始化處理。
(4).異步加載的方式二:defer 異步加載 :
<script type="text/javascript" src="example.js" defer="defer"></script>
defer
異步加載,但要等到dom文檔全部解析完才能被執行。只有IE能用,可以把代碼寫在script標籤裏
(5).異步加載的方式三:async 異步加載:
<script type="text/javascript" src="example.js" async="async"></script>
async
異步加載,加載完就執行,async只能加載外部腳本,不能把js代碼寫在script標籤裏