如果您不是動態加載腳本或將它們標記爲延遲或異步,則會按頁面中遇到的順序加載腳本。無論它是外部腳本還是內聯腳本都無關緊要 - 它們按頁面中遇到的順序執行。在外部腳本之後的內聯腳本一直保留,直到所有外部腳本加載並運行。
異步腳本(無論它們如何指定爲異步)加載並以不可預知的順序運行。瀏覽器並行加載它們,並且可以按照它想要的順序自由運行它們。
在多個異步事件中沒有可預測的順序。如果需要一個可預測的順序,那麼它將不得不通過註冊來自異步腳本的加載通知進行編碼,並在加載適當的東西時手動排序JavaScript調用。
當動態插入腳本標記時,執行順序的行爲方式取決於瀏覽器。您可以看到Firefox在this reference article中的行爲。簡而言之,較新版本的Firefox會默認動態添加腳本標記以進行異步操作,除非腳本標記已被設置。
帶有async
的腳本標記可能會在加載後立即運行。事實上,瀏覽器可能會暫停解析器,並執行該腳本。所以,它幾乎可以在任何時候運行。如果腳本被緩存了,它可能立即運行。如果腳本需要一段時間才能加載,則可能在解析器完成後運行。 async
要記住的一點是,它可以隨時運行,而且這個時間是不可預測的。
一個帶有defer
的腳本標籤會一直等到整個解析器完成,然後以遇到的順序運行標有defer
的所有腳本。這允許您標記幾個相互依賴的腳本,如defer
。它們都會被推遲到文檔解析器完成之後,但它們將按照遇到它們的依賴關係的順序執行。我認爲defer
就像腳本被放入隊列中一樣,解析器完成後將處理它。從技術上講,瀏覽器可能會隨時在後臺下載腳本,但直到解析器完成解析頁面並解析並運行任何未標記爲延遲或異步的內聯腳本後,它們纔會執行或阻止解析器。
下面是這篇文章報價:
腳本插入腳本在IE和WebKit異步執行,但 同步在Opera和4.0版本之前的Firefox瀏覽器。
HTML5規範的相關部分(適用於更新的兼容瀏覽器)爲here。那裏寫了很多關於異步行爲的內容。顯然,這個規範並不適用於那些您可能需要測試才能確定的行爲的舊瀏覽器(或不確定的瀏覽器)。
從HTML5規範中的一個報價:
然後,第一的描述的情況 下列選項必須遵循:
如果該元素具有src屬性和元素具有延遲 屬性,並且該元素已被標記爲「解析器插入」,並且該元素不具有異步屬性 該元素必須被添加 到腳本列表的末尾t當文檔 完成與解析器的文檔相關聯的解析, 創建該元素時,帽子將執行。
,關於任務隊列的網絡任務源的地方,一旦 的取算法已完成必須設置元素的「準備 是解析器執行的」標誌的任務。解析器將處理執行腳本。
如果元件具有src屬性,並且元件已被標記 爲「解析器插入」,而元件不具有一個異步屬性 元素是文檔的待決解析阻擋腳本 創建元素的解析器。 (只能有每個文檔的一個這樣的 腳本在同一時間。)
,一旦 的取算法已經完成了任務隊列的網絡任務源場所必須設置元素的「準備 是parser-任務執行「的標誌。解析器將處理執行腳本。
如果元件不具有src屬性,並且元件已 標記爲「解析器插入」,並且HTML解析器或 XML解析器創建的腳本元素的文檔具有樣式表是 阻止腳本該元素是 創建元素的解析器的Document的暫掛解析阻止腳本。 (一次只能有 爲每個文檔一個這樣的腳本。)
設置元素的「準備好解析器執行」標誌。解析器將會執行腳本 。
如果該元素具有src屬性,不具備異步特性, 和不具備「強制異步」標誌設置元素必須添加 到腳本,將列表的末尾按照儘可能快的 的順序執行與腳本元素的文檔相關聯的 時刻準備腳本算法開始。
,關於任務隊列的網絡任務源的地方,一旦 的取算法已經完成了必須執行下列步驟的任務:
如果元素是不是現在在腳本 列表中的第一個元素將盡快按順序執行,將 添加到上面,然後將該元素標記爲準備好,但會中止這些步驟,而不執行 執行腳本。
執行:執行該腳本列表中的第一個腳本 元素所對應的腳本塊,該腳本將盡快按照 的順序執行。
從此腳本列表中刪除第一個元素,它將盡快按順序執行 。
如果將爲了儘快執行儘可能 仍然不爲空,首先進入已經被標記爲 準備腳本的清單,然後跳回一步標記執行。
如果該元素具有src屬性元素必須被添加到 組將在時儘快腳本元素的文檔 的執行編寫一個腳本算法 啓動腳本。
的任務在任務隊列,一旦 的取算法已經完成了必須執行的腳本塊和 聯網任務源的地方,然後從組腳本,將立即執行 儘可能刪除元素。
否則即使其他腳本已經在執行,用戶代理也必須立即執行腳本塊 。
你有沒有看[加載腳本而不阻塞(https://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/)由史蒂夫Souders的?現在有點過時了,但是在給定特定腳本加載技術的情況下,仍然包含瀏覽器行爲的一些有價值的見解。 –