日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之defer與async特性

defer和async特性相信是很多JavaScript開(kāi)發(fā)者"熟悉而又不熟悉"的兩個(gè)特性,從字面上來(lái)看,二者的功能很好理解,分別是"延遲腳本"和"異步腳本"的作用 。然而,以defer為例,一些細(xì)節(jié)問(wèn)題可能開(kāi)發(fā)者卻并不一定熟悉,比如:有了defer特性的腳本會(huì)延遲到什么時(shí)候執(zhí)行;內(nèi)部腳本和外部腳本是不是都能夠支持defer;defer后的腳本除了會(huì)延遲執(zhí)行之外,還有哪些特殊的地方等等 。本文結(jié)合已有的一些文章以及MDN文檔中對(duì)兩個(gè)特性的闡述,對(duì)defer和async進(jìn)行更全面的研究和總結(jié),希望能夠幫助開(kāi)發(fā)者更好地掌握這兩個(gè)特性 。
1 引言
在《瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之代碼執(zhí)行順序》中我們提到過(guò),JavaScript代碼的執(zhí)行會(huì)阻塞頁(yè)面的解析渲染以及其他資源的下載,當(dāng)然由于JavaScript是單線(xiàn)程語(yǔ)言,那就意味著在正常情況下,一個(gè)頁(yè)面中的JavaScript代碼只能按順序從上到下執(zhí)行,當(dāng)然,正如《瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之代碼執(zhí)行順序》中我們分析的,在某些情況下,比如通過(guò)document.write進(jìn)入腳本或者通過(guò)動(dòng)態(tài)腳本技術(shù)引入腳本時(shí),JavaScript代碼的執(zhí)行順序不一定嚴(yán)格按照從上到下的順序,而defer和async也是我們所說(shuō)的"非正常的情況" 。
我們經(jīng)常會(huì)說(shuō)JavaScript的執(zhí)行具有阻塞性,而在實(shí)際的開(kāi)發(fā)中,我們通常最關(guān)心的阻塞,同時(shí)也是最影響用戶(hù)體驗(yàn)的阻塞應(yīng)該是以下幾個(gè)方面:
[1]頁(yè)面解析和渲染的阻塞
[2]我們寫(xiě)的頁(yè)面初始化腳本(一般是監(jiān)聽(tīng)DOMContentLoaded事件所綁定的腳本,這部分腳本是我們希望最先執(zhí)行的腳本,因?yàn)槲覀儠?huì)把和用戶(hù)交互最相關(guān)的代碼寫(xiě)在這里)
[3]頁(yè)面外部資源下載的阻塞(比如圖片)
如果我們有一個(gè)耗時(shí)的腳本操作,而這段腳本又阻塞了上面我們提到的這三個(gè)地方,那么這個(gè)網(wǎng)頁(yè)的性能或者用戶(hù)體驗(yàn)就非常差了 。
defer和async這兩個(gè)特性的初衷也是希望能夠解決或者緩解阻塞對(duì)于頁(yè)面體驗(yàn)的影響,下面我們就來(lái)分析一下這兩個(gè)特性,我們主要從以下幾個(gè)方面來(lái)全方位了解這兩個(gè)特性:
[1]延遲或異步的腳本的執(zhí)行時(shí)機(jī)是什么時(shí)候?對(duì)于頁(yè)面的阻塞情況如何?
[2]內(nèi)部腳本和外部腳本是否都能夠?qū)崿F(xiàn)延遲或異步?
[3]瀏覽器對(duì)這兩個(gè)特性的支持情況如何?有沒(méi)有相關(guān)的bug?
[4]使用了這兩個(gè)特性的腳本在使用時(shí)還有什么需要注意的地方?
2 defer特性
2.1 關(guān)于defer腳本的執(zhí)行時(shí)機(jī)
defer特性是HTML4規(guī)范中定義的擴(kuò)展特性,最初只有IE4 和firefox3.5 才支持,之后chrome等瀏覽器也增加了對(duì)它的支持,使用的方式為defer="defer" 。defer意為延遲,也就是會(huì)延遲腳本的執(zhí)行 。正常情況下,我們引入的腳本會(huì)被立即下載和執(zhí)行,而有了defer特性之后,腳本下載完畢后不會(huì)立即執(zhí)行,而是等到頁(yè)面解析完畢之后再執(zhí)行 。我們看一下HTML4標(biāo)準(zhǔn)對(duì)defer的闡述:
defer:When set, this boolean attribute provides a hint to the user agent that the script is not going to generate any document content (e.g., no "document.write" in javascript) and thus, the user agent can continue parsing and rendering.
也就是說(shuō),如果設(shè)置了defer,那么就告訴用戶(hù)代理,這個(gè)腳本不會(huì)產(chǎn)生任何文檔內(nèi)容,從而用戶(hù)代理可以繼續(xù)解析和渲染 。我們?cè)倏匆幌翸DN中對(duì)defer的關(guān)鍵描述:
defer:If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing.
通過(guò)標(biāo)準(zhǔn)中的定義,我們可以明確,即:defer的腳本不會(huì)阻塞頁(yè)面的解析,而是等到頁(yè)面解析結(jié)束之后再執(zhí)行,但是耗時(shí)的defer依然可能會(huì)阻塞外部資源的下載,那么它會(huì)阻塞DOMContentLoaded事件么?事實(shí)上,defer的腳本依然是在DOMContentLoaded事件之前執(zhí)行的,因此它還是會(huì)阻塞DOMContentLoaded中的腳本 。我們可以通過(guò)下圖來(lái)幫助理解defer腳本的執(zhí)行時(shí)機(jī):

推薦閱讀