script標(biāo)簽是我們常用的引用js腳本的一種方式。
擼代碼的時(shí)候驳庭,我們常常只寫src屬性刑顺,直接忽略其他的屬性:async、defer
顧名思義async就是異步饲常,在不影響其他資源加載的同時(shí)蹲堂,異步加載這個(gè)文件;defer就是延遲加載贝淤。
async: 可選屬性柒竞。表示應(yīng)該立即下載腳本,但不應(yīng)妨礙頁面中的其他操作播聪,比如下載其他資源或等待加載其他腳本朽基。只對(duì)外部腳本文件有效(寫在html文件中的js代碼布隔,添加此屬性無效,仍按代碼加載順序執(zhí)行)稼虎。
defer: 可選屬性衅檀。標(biāo)識(shí)腳本可以延遲到文檔完全被解析和顯示之后再執(zhí)行。只對(duì)外部腳本文件有效霎俩。
Html代碼:
進(jìn)入的js文件中哀军,同文件序號(hào)分別console.log,1,2,3,4,5,6;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>test1 test2</h1>
</body>
<script defer>
console.log(0)
</script>
<script src='js1.js'></script>
<script src='js2.js'></script>
<script src='js3.js'></script>
<script src='js4.js'></script>
<script src='js5.js'></script>
<script src='js6.js'></script>
</html>
在瀏覽器中打開這個(gè)html文件打却,我們可以看到6個(gè)js文件按照順序加載杉适。
OK.現(xiàn)在我給js1文件加上defer屬性,看看柳击。
<script defer src='js1.js'></script>
實(shí)驗(yàn)證明:
js文件依然按照書寫順序加載淘衙,在控制臺(tái)可以看到,js1文件的代碼是最后執(zhí)行的腻暮。
那我們還原代碼彤守,給js6文件加上async屬性試試,看看會(huì)不會(huì)第一個(gè)輸出6
<script async src='js6.js'></script>
很遺憾哭靖,實(shí)時(shí)并沒有按照預(yù)想的那樣輸出6具垫,0,1试幽,2筝蚕,3,4铺坞,5
如上圖代碼還是按照順序執(zhí)行了起宽,為什么defer生效了,async沒生效呢济榨?
我們換個(gè)文件試試坯沪,給中間位置的某個(gè)文件添加async屬性。我給js3加了async屬性后擒滑,代碼執(zhí)行順序發(fā)生了如下變化:
我們都知道腐晾,js是按照書寫順序加載,按照書寫順序執(zhí)行的丐一。文件加載之后藻糖,程序便開始解析文件中的代碼。
因此添加了async屬性的文件库车,需要加載到這個(gè)文件位置的時(shí)候才會(huì)生效巨柒,js6已經(jīng)是最后一個(gè)文件了,最后一個(gè)加載的文件中的代碼自然就最后執(zhí)行,因此看起來async在我們的第一個(gè)demo中沒有生效洋满。
async是異步加載晶乔,而不是優(yōu)先加載,因此js3文件添加了async屬性后芦岂,當(dāng)文件加載到j(luò)s3,同時(shí)開始加載js3之后的文件瘪弓,于是便出現(xiàn)了上圖0,1,2,4,3,5,6的結(jié)果垫蛆,當(dāng)然這個(gè)結(jié)果不是必然的禽最,因?yàn)槲覀兊膁emo里面的代碼非常簡(jiǎn)短,如果js4中的代碼邏輯復(fù)雜袱饭,那么結(jié)果可能任然是0,1,2,3,4,5,6川无。
說到這里,大家明白async和defer的原理了吧虑乖。
總結(jié):那么什么場(chǎng)景下可以用到這些屬性呢懦趋?
比如有些第三方庫,要求在header中引入(這就意味著第三方插件庫會(huì)優(yōu)先加載)疹味,但是我們并不需要在頁面加載之初就用到這個(gè)插件仅叫。那么我們可以加上defer屬性使之最后加載。同理糙捺,如果頁面加載的同時(shí)需要用到第三方插件诫咱,那么我們引用的時(shí)候可以加async屬性,這樣網(wǎng)站內(nèi)的資源就可以與插件資源異步加載洪灯。這中方法會(huì)給網(wǎng)站其他資源的加載節(jié)省出一些時(shí)間坎缭,不失為一種頁面優(yōu)化的方法。