解釋器對<script>中內容的加載方式
解析嵌入式JavaScript代碼:在解釋器對<script>元素內部的所有代碼求值完畢之前,頁面中的其餘內容都不會被瀏覽器加載或顯示。
解析外部JavaScript文件:在解析外部文件,包括下載該文件時,頁面的處理也會暫時停止。
只要不存在defer或async屬性,瀏覽器都會按照<script>元素在頁面中出現的先後順序對它們一次進行解析。
而這種加載方式可能會導致問題,在腳本加載和執行的過程中,會阻塞後續的DOM渲染。例如,在頁面中引用第三方腳本時,如果第三方服務商出現了一些小問題,比如延遲之類的,就會使得頁面白屏。
解決方案:使用<script>
元素的async
或defer
屬性。
script標籤的位置
傳統做法放在<head>元素中(不推薦)
但這意味着必須等到全部JavaScript代碼都被下載解析和執行完後,才能開始呈現頁面的內容,瀏覽器在遇到<body>標籤時纔開始呈現內容。
而對於那些需要加載很多JavaScript代碼的頁面來說,則會導致瀏覽器再呈現頁面時出現明顯的延遲,而在延遲期間的瀏覽器窗口會是一片空白。
放在<body>元素中頁面內容的後面
<body>
<!---頁面內容-->
<script type="text/javascript" src="example1.js"></script>
<script type="text/javascript" src="example2.js"></script>
</body>
延遲腳本和異步腳本
延遲腳本:defer屬性
defer屬性用於表明腳本在執行時不會影響頁面的構造,即,表明腳本會被延遲到整個頁面都解析完畢後再運行。
<script type="text/javascript" defer="defer" src="example.js"></script>
對於腳本執行的先後順序,HTML5規範和實際執行過程中不一樣:
- HTML5規範要求腳本按照它們出現的先後順序執行。第一個延遲腳本會先於第二個延遲腳本執行,且所有延遲腳本都會先於DOMContentLoaded事件執行。
- 實際執行過程中,延遲腳本並不一定會按順序執行,也不一定會在DOMContentLoaded事件觸發前執行。
因此,最好只包含一個延遲腳本。
異步腳本:async屬性
async屬性只使用與外部腳本文件。async的目的是爲了不讓頁面等待腳本下載和執行,從而異步加載頁面其他內容。
<script type="text/javascript" async src="example.js"></script>
但是,標記爲async的腳本並不保證按照指定他們的先後順序執行。也正因爲這一點,確保要加載的腳本間互不依賴。也由於是異步加載頁面其他內容,異步腳本再加載期間也最好不要修改DOM。