script執(zhí)行
瀏覽器在執(zhí)行HTML的時(shí)候如果遇到<script>時(shí)會(huì)停止頁面的渲染,去下載和執(zhí)行js的文件直接遇見</scirpt>會(huì)繼續(xù)渲染頁面从祝。故瀏覽器在執(zhí)行js文件的時(shí)候?yàn)g覽器表現(xiàn)為一片空白,為了解決這個(gè)問題ECMAScript定義了defer和async兩個(gè)屬性用于控制JS的下載和執(zhí)行
async是在HTML5中加入的
defer
對(duì)于defer怜跑,我們可以認(rèn)為是將外鏈的js放在了頁面底部名船。js的加載不會(huì)阻塞頁面的渲染和資源的加載。不過defer會(huì)按照原本的js的順序執(zhí)行,所以如果前后有依賴關(guān)系的js可以放心使用
async
和defer一樣,會(huì)等待的資源不會(huì)阻塞其余資源的加載崎弃,也不會(huì)影響頁面的加載甘晤。但是有一點(diǎn)需要注意下,在有async的情況下饲做,js一旦下載好了就會(huì)執(zhí)行线婚,所以很有可能不是按照原本的順序來執(zhí)行的。如果js前后有依賴性盆均,用async塞弊,就很有可能出錯(cuò)。
區(qū)別
相同點(diǎn):
- 加載文件時(shí)不阻塞頁面渲染
- 對(duì)于inline的script無效
- 使用這兩個(gè)屬性的腳本中不能調(diào)用document.write方法
- 有腳本的onload的事件回調(diào)
區(qū)別點(diǎn):
- html4.0中定義了defer泪姨;html5.0中定義了async
- 瀏覽器支持不同
- 每一個(gè)async屬性的腳本都在它下載結(jié)束之后立刻執(zhí)行游沿,同時(shí)會(huì)在window的load事件之前執(zhí)行。所以就有可能出現(xiàn)腳本執(zhí)行順序被打亂的情況驴娃;每一個(gè)defer屬性的腳本都是在頁面解析完畢之后奏候,按照原本的順序執(zhí)行,同時(shí)會(huì)在document的DOMContentLoaded之前執(zhí)行唇敞。
簡(jiǎn)單的來說蔗草,使用這兩個(gè)屬性會(huì)有三種可能的情況
- 如果async為true,那么腳本在下載完成后異步執(zhí)行疆柔。
- 如果async為false咒精,defer為true,那么腳本會(huì)在頁面解析完畢之后執(zhí)行旷档。
- 如果async和defer都為false模叙,那么腳本會(huì)在頁面解析中,停止頁面解析鞋屈,立刻下載并且執(zhí)行
無論使用defer還是async屬性范咨,都需要首先將頁面中的js文件進(jìn)行整理,哪些文件之間有依賴性厂庇,哪些文件可以延遲加載等等渠啊,做好js代碼的合并和拆分,然后再根據(jù)頁面需要使用這兩個(gè)屬性
疑惑
在《JavaScript高級(jí)程序設(shè)計(jì)》的P13中提到
在現(xiàn)實(shí)中,延遲腳本并不一定會(huì)按照順序執(zhí)行,也不一定會(huì)在DOMContentLoaded事件觸發(fā)前執(zhí)行,因此最好包含一個(gè)延遲腳本
原文如下:
In reality, though, deferred scriptsdon’t always execute in order or before the DOMContentLoaded event, so it’s best to include just onewhen possible.
那么什么情況下defer會(huì)不按照順序執(zhí)行