【筆記】JS指令碼為什麼要放在body最後面以及async和defer的異同點

SoulDee發表於2018-07-20

1.沒有deferasync

瀏覽器遇到指令碼的時候會暫停渲染並立即載入執行指令碼(外部指令碼),“立即”指的是在渲染該 script 標籤之下的文件元素之前,也就是說不等待後續載入的文件元素,讀到就載入並執行。因此如果將JS指令碼放置在head的話會產生阻塞,並且指令碼當中對於DOM的操作也會出現報錯,因為還沒有生成。

放在body底部的JS指令碼的執行順序是按照在文件中的先後順序執行的,而不是按照下載下的順序

2.有async過程如下:

1.瀏覽器開始解析網頁

2.解析過程中,發現帶有async屬性的script標籤

3.瀏覽器繼續往下解析 HTML 網頁,同時並行下載外部指令碼

4.指令碼下載完成,瀏覽器暫停解析網頁,開始執行下載的指令碼

5.指令碼執行完畢,瀏覽器恢復解析網頁

async指令碼執行順序是下載的順序

3.有defer過程如下:

1.瀏覽器開始解析網頁

2.解析過程中,發現帶有defer屬性的指令碼元素

3.瀏覽器繼續往下解析網頁,同時並行下載指令碼元素載入的外部指令碼

4.瀏覽器完成解析網頁,此時再回過頭執行已經下載完成的指令碼

defer指令碼執行順序是出現的先後順序

4.defer還是async

兩者之間的選擇則是看指令碼之間是否有依賴關係,有依賴的話應當要保證執行順序,應當使用defer沒有依賴的話使用async,同時使用的話defer失效。要注意的是兩者都不應該使用document.write,這個導致整個頁面被清除。

瀏覽器完整過程是先解析渲染HTML,當遇到指令碼檔案的時候則執行指令碼檔案,等待指令碼檔案執行完畢才繼續解析html,因此會產生阻塞頁面的情況,因此最好將指令碼放在body底部,當瀏覽器遇到標有defer的時候則會下載該指令碼,同是繼續解析html,然後等到dom解析完畢之後才解析defer指令碼,而如果遇到async指令碼的時候同樣是下載該指令碼同是繼續解析html,當anync下載完畢之後,而html尚未解析完畢,也會先解析async指令碼,等待async指令碼解析完畢之後才繼續解析html。

詳細的過程對比參考下圖:

【筆記】JS指令碼為什麼要放在body最後面以及async和defer的異同點

參考

阮一峰JS教程

JavaScript高階程式

document.write的用處

相關文章