<script>標(biāo)簽元素?
可選屬性:
?async:?不用等待腳本下載執(zhí)行完后再加載頁(yè)面奸柬,也不需要等待異步腳本加載完成后再加載其他腳本。
? ? ? ? ? ? 有async標(biāo)簽的腳本不能保證按照出現(xiàn)的次序執(zhí)行调鲸。
charset:?src指定的代碼的字符集
crossorigin:?配置相關(guān)請(qǐng)求的跨資源共享設(shè)置(CORS)剂癌。默認(rèn)不使用蹂随。crossorigin="anonymous"配置文件請(qǐng)求不必設(shè)置憑據(jù)標(biāo)志琉预。crossorigin="use-credentials"設(shè)置憑據(jù)標(biāo)志,出站請(qǐng)求會(huì)包含憑據(jù)
defer:?表示腳本可以等到文檔解析或顯示完成后再執(zhí)行姐直。 瀏覽器會(huì)忽略行內(nèi)腳本的defer屬性
intergrity:?允許比對(duì)接受到的資源和指定的加密簽名以驗(yàn)證資源的完整性倦淀。簽名不匹配會(huì)報(bào)錯(cuò)。
type:?代替language屬性声畏,始終是"text/javascript"
? ? ? ? ?如果值是"module"撞叽,代碼會(huì)被當(dāng)成ES6模塊且只有這種情況代碼中才能出現(xiàn)import/export關(guān)鍵字
src:? ?外部文件地址。使用src屬性的<script>元素插龄,會(huì)忽略標(biāo)簽內(nèi)的行內(nèi)代碼愿棋。
? ? ? ? ?瀏覽器不會(huì)檢查外部文件的擴(kuò)展名,但是要保證返回正確的MINE類型均牢。
行內(nèi)腳本如果包含</script>字符串時(shí)糠雨,需要添加轉(zhuǎn)義字符。如:
<script>
? ? function test () {
? ? ? ? ? ? ?console.log("</script>");
? ? ? ? ? ? console.log("<\/script>");
????}
</script>
<script>標(biāo)簽位置
<script>元素至于頁(yè)面的<head>標(biāo)簽內(nèi)徘跪,目的主要是把外部的css和js文件集中到一起甘邀。但是這樣有一個(gè)不好的地方。? ? 必須把所有的JavaScript代碼下載垮庐、解析和解釋完成以后松邪,才能開始渲染頁(yè)面。對(duì)于大量外部js引入的頁(yè)面哨查,加載的時(shí)間內(nèi)瀏覽器窗口將完全空白逗抑。
優(yōu)化方式一般是,把<script>元素移植<body>標(biāo)簽內(nèi)的結(jié)尾處解恰。
當(dāng)然也可以給<head>標(biāo)簽中的 7姘恕!外部;び挟纱! <script>元素添加defer屬性。
或者添加async屬性來(lái)異步加載腐宋。
<script>元素的加載順序
1.HTML5規(guī)范要求腳本按照出現(xiàn)的順序執(zhí)行紊服。
2.如果外部腳本申明了defer屬性,它們會(huì)在瀏覽器執(zhí)行到</html>標(biāo)簽結(jié)束后才會(huì)執(zhí)行胸竞,且如果有多個(gè)defer屬性欺嗤,按照規(guī)范也會(huì)按照出現(xiàn)順序相應(yīng)地延遲執(zhí)行。
這里就會(huì)有一個(gè)問(wèn)題卫枝。如果我在</html>標(biāo)簽之后手動(dòng)添加了行內(nèi)<script>或者外部<script>(叫腳本B吧)煎饼,并且我在<head>標(biāo)簽內(nèi)引入了外部<sctipt>(叫腳本A吧),并且腳本A定義了defer屬性校赤。那么實(shí)際渲染過(guò)程中A, B的執(zhí)行順序是什么樣的吆玖。這里書中目前并沒(méi)有看到筒溃,自己做一個(gè)簡(jiǎn)單的測(cè)試。
如圖沾乘,我們先測(cè)試正常情況下的logs順序怜奖,引入的testorder.js內(nèi)容為console.log('A');
它的輸出結(jié)果如同預(yù)期。
然后我們給外部引入的script添加defer屬性翅阵,看看它是什么樣的輸出結(jié)果:
按照理解的話應(yīng)該是B C A D歪玲,那么結(jié)果如何呢:
這樣寫可能不太清晰,那我們多加幾個(gè)引用:(外部腳本分別log A1 A2 A3 A4)
輸出結(jié)果呢:
那么我們的第二點(diǎn)標(biāo)題可能需要改寫了掷匠,其實(shí)是
如果外部腳本申明了defer屬性滥崩,它們會(huì)在瀏覽器執(zhí)行到</html>標(biāo)簽結(jié)束后且在頁(yè)面內(nèi)的其他無(wú)defer屬性的<script>執(zhí)行后才會(huì)執(zhí)行,且如果有多個(gè)defer屬性槐雾,按照規(guī)范也會(huì)按照出現(xiàn)順序相應(yīng)地延遲執(zhí)行夭委。
其實(shí)還有一個(gè)小問(wèn)題幅狮,如果帶上了setTimeout以后的順序是不是還是如此募强。
A1延遲200, A2延遲100崇摄, A3延遲50擎值,A4延遲1,C延遲10逐抑,D2延遲100
實(shí)際的輸出就需要理解一下了:
3.HTML5 規(guī)范要求腳本按照它們出現(xiàn)的先后順序執(zhí)行鸠儿,因此第一個(gè)延遲腳本會(huì)先于第二個(gè)延遲腳本執(zhí)行,而這兩個(gè)腳本會(huì)先于 DOMContentLoaded 事件執(zhí)行厕氨。在現(xiàn)實(shí)當(dāng)中进每,延遲腳本并不一定會(huì)按照順序執(zhí)行,也不一定會(huì)在 DOMContentLoaded 事件觸發(fā)前執(zhí)行命斧,因此最好只包含一個(gè)延遲腳本田晚。(defer)
個(gè)人測(cè)試沒(méi)有出現(xiàn)過(guò)延后的情況。個(gè)人感覺(jué)書上這么寫的原因可能是因?yàn)椋?HTML5規(guī)范如此国葬,但是每個(gè)瀏覽器廠商未必會(huì)按照這個(gè)規(guī)范實(shí)現(xiàn)(有待考究)
4.async 只適用于外部腳本文件贤徒,并告訴瀏覽器立即下載文件,下載完成后立即執(zhí)行汇四。但與?defer不同的是接奈,標(biāo)記為 async 的腳本并不保證按照指定它們的先后順序執(zhí)行。async腳本可以保證在load事件前執(zhí)行通孽,但是有可能在DOMContentLoaded事件之前或之后序宦。
有關(guān)DOMContentLoaded 與 load區(qū)別,可以參見演示鏈接背苦。
5.(補(bǔ)充)async和defer的區(qū)別
這里引用一下知乎@ 編譯青春的文章互捌,講的比較詳細(xì)與直觀 :?你不知道的 DOMContentLoaded
動(dòng)態(tài)加載腳本
以這種方式獲取的資源對(duì)瀏覽器的預(yù)加載器是不可見的堡僻,這回嚴(yán)重影響到它們?cè)谫Y源獲取隊(duì)列中的優(yōu)先級(jí)。
想讓預(yù)加載器知道這些動(dòng)態(tài)請(qǐng)求文件的存在疫剃,可以再文檔頭部顯示申明它們:<link rel="preload" href="gibberish.js">
同樣钉疫,我們來(lái)試驗(yàn)一下動(dòng)態(tài)加載的效果:
異步的情況(會(huì)出現(xiàn)多種結(jié)果,只列舉2種):
同步的情況
無(wú)論是否設(shè)置同步巢价,動(dòng)態(tài)加載都會(huì)出現(xiàn)多種不同結(jié)果(只列舉三種): 但是順序只有兩種 動(dòng)態(tài)加載的order2在 申明defer的1,3之前或者之后牲阁。
多種結(jié)果具體是為什么,個(gè)人壤躲,猜測(cè)城菊,是因?yàn)閯?dòng)態(tài)引入的時(shí)候,會(huì)根據(jù)加載的速度碉克,在加載完成后對(duì)HTML文檔解析過(guò)程進(jìn)行一個(gè)中斷凌唬。
XHTML中的變化
XHTML中,行內(nèi)腳本小于號(hào)(<)會(huì)被解釋成標(biāo)簽開始漏麦,所以需要替換成(<)
或者使用 "<![CDATA[ "? ? ? "? ]]> "來(lái)包裹行內(nèi)腳本客税。
<noscript>元素
不支持JavaScript時(shí)會(huì)顯示標(biāo)簽內(nèi)元素。