默認(rèn)情況下捅彻,瀏覽器是同步加載 JavaScript 腳本,即渲染引擎遇到<script>標(biāo)簽就會(huì)停下來鞍陨,等到執(zhí)行完腳本(如果是用src引用的外聯(lián)腳本文件,遇到<script>標(biāo)簽會(huì)開始下載文件然后執(zhí)行)从隆,再繼續(xù)向下渲染诚撵。
如果腳本體積很大,下載和執(zhí)行的時(shí)間就會(huì)很長(zhǎng)键闺,因此造成瀏覽器堵塞寿烟,用戶會(huì)感覺到瀏覽器“卡死”了,沒有任何響應(yīng)辛燥。這顯然是很不好的體驗(yàn)筛武,所以瀏覽器允許腳本異步加載,<script>標(biāo)簽提供的async屬性與defer屬性可以實(shí)現(xiàn)腳本文件的異步加載:
1. defer屬性
表示腳本可以延遲到文檔完全被解析和顯示之后再執(zhí)行挎塌。只對(duì)外本腳本文件有效徘六。
瀏覽器的解析順序:
- 瀏覽器開始解析 HTML 網(wǎng)頁(yè)。
- 解析過程中榴都,發(fā)現(xiàn)帶有defer屬性的<script>元素待锈。
- 瀏覽器繼續(xù)往下解析 HTML 網(wǎng)頁(yè),同時(shí)并行下載<script>元素加載的外部腳本嘴高。
- 瀏覽器完成解析 HTML 網(wǎng)頁(yè)竿音,此時(shí)再回過頭執(zhí)行已經(jīng)下載完成的腳本。
2. async屬性
表示應(yīng)該立即下載腳本拴驮,但不應(yīng)該妨礙頁(yè)面中的其他操作春瞬,比如下載其他資源或等待加載其他腳本。只對(duì)外部文件有效套啤。
瀏覽器的解析順序:
- 瀏覽器開始解析 HTML 網(wǎng)頁(yè)宽气。
- 解析過程中,發(fā)現(xiàn)帶有async屬性的script標(biāo)簽纲岭。
- 瀏覽器繼續(xù)往下解析 HTML 網(wǎng)頁(yè)抹竹,同時(shí)并行下載<script>標(biāo)簽中的外部腳本。
- 腳本下載完成止潮,瀏覽器暫停解析 HTML 網(wǎng)頁(yè)窃判,開始執(zhí)行下載的腳本。腳本執(zhí)行完畢喇闸,瀏覽器恢復(fù)解析 HTML 網(wǎng)頁(yè)袄琳。
需要注意的是询件,一旦采用這個(gè)屬性,就無法保證腳本的執(zhí)行順序唆樊。哪個(gè)腳本先下載結(jié)束宛琅,就先執(zhí)行那個(gè)腳本。
3. defer與async的區(qū)別
- defer要等到整個(gè)頁(yè)面在內(nèi)存中正常渲染結(jié)束(DOM 結(jié)構(gòu)完全生成逗旁,以及其他腳本執(zhí)行完成)嘿辟,才會(huì)執(zhí)行;
- async一旦下載完片效,渲染引擎就會(huì)中斷渲染红伦,執(zhí)行這個(gè)腳本以后,再繼續(xù)渲染淀衣。
- 一句話昙读,defer是“渲染完再執(zhí)行”,async是“下載完就執(zhí)行”膨桥。
- 如果有多個(gè)defer腳本蛮浑,會(huì)按照它們?cè)陧?yè)面出現(xiàn)的順序加載,而多個(gè)async腳本是不能保證加載順序的只嚣。