首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JavaScript 檔案引用方式與同步/非同步執行機制深度解析

     編輯:Java 相關知識

前言

在前端開發中,JavaScript 檔案的引入方式直接影響頁面載入效能與腳本執行順序。本文將系統性梳理各種引用方法的同步與非同步特性,並透過實測代碼驗證瀏覽器行為差異,幫助開發者做出最佳選擇。

核心結論速覽

  • 原生 <script> 標籤:預設同步載入並阻塞渲染
  • document.write 引入:在內聯腳本中屬非同步,但在外部腳本中又變同步
  • createElement + appendChild:標準非同步載入方式
  • 現代屬性 async/defer:HTML5 標準化的非同步控制

五大引用場景詳細分析

1. 內聯腳本 — 同步執行

<script> 
  // 同步載入執行的代碼 
</script>

瀏覽器解析到此處會立即執行,阻塞後續 DOM 解析與渲染。

2. 外部腳本 src 屬性 — 同步載入

<script src="xx.js"></script> 
// 同步載入執行 xx.js 中的代碼

下載、解析、執行全過程阻塞主線程,按文檔順序依序執行。

3. 內聯腳本中 document.write 引入 — 非同步執行

<script> 
  document.write('<script src="xx.js"><\/script>'); 
  // 非同步載入執行 xx.js 中的代碼 
</script>

document.write 會將腳本注入文檔流,但瀏覽器不保證立即執行,屬非同步行為。

4. 外部腳本中 document.write 連鎖引入 — 同步執行

<script src="xx.js"></script> 
// xx.js 內容:
document.write('<script src="11.js"><\/script>');
document.write('<script src="22.js"><\/script>');

此時 11.js、22.js 會同步載入並按順序執行。若 xx.js 本身以非同步方式載入,內部鏈仍保持同步特性(即「非同步中的同步」)。

5. 動態創建 script 標籤 — 標準非同步載入

var script = document.createElement("script");
script.setAttribute("src", "xx.js");
document.getElementsByTagName("head")[0].appendChild(script);

此為主流非阻塞載入模式,需配合 onload/onreadystatechange 實現回調。

通用非同步載入函數封裝

var loadJS = function(url, callback) {
  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  script.src = url;
  script.type = "text/javascript";
  head.appendChild(script);
  
  script.onload = script.onreadystatechange = function() {
    // IE 下有 onreadystatechange,W3C 標準有 onload
    // readyState 针对 IE8 及以下
    if ((!this.readyState) || this.readyState === "complete" || this.readyState === "loaded") {
      callback();
    } else {
      alert("can not load the js file");
    }
  };
};

跨瀏覽器實測驗證

測試環境:tryjs.html 主頁 → tryjs.js(document.write 引入 try.1.js、try.2.js)

IE 7/8 執行順序

outer js callback loading IE
outer js callback loaded IE
write begin
write finished
outer js callback complete IE
file 1 callback loading IE
file 2 callback loading IE
loadjs 1 begin
loadjs 1 finished
loadjs 2 begin
loadjs 2 finished
file 2 callback complete IE
file 1 callback complete IE

IE 9 執行順序

write begin
write finished
outer js callback complete IE
file 1 callback loading IE
file 2 callback loading IE
loadjs 1 begin
loadjs 1 finished
loadjs 2 begin
loadjs 2 finished
file 1 callback complete IE
file 2 callback complete IE

Firefox / Chrome 執行順序

write begin
write finished
outer js callback, not IE
loadjs 1 begin
loadjs 1 finished
file 1 callback, NOT IE
loadjs 2 begin
loadjs 2 finished
file 2 callback, NOT IE

關鍵發現

  1. IE 9+ 與現代瀏覽器:外部腳本 onload 觸發時機提前至 document.write 完成後
  2. document.write 連鎖:在同步腳本中仍保持同步順序,但在非同步腳本中行為不一
  3. 回調順序差異:IE 7/8 的 complete 回調順序與現代瀏覽器相反

最佳實踐建議

  • 優先使用 <script src="..." defer> 延遲執行(保持順序)
  • 獨立模組使用 async 並行載入(不保證順序)
  • 動態載入配合 Promise/async-await 管理依賴
  • 避免 document.write,已被標準棄用且阻塞解析器
  • 關鍵渲染路徑腳本內聯,非關鍵腳本非同步載入

總結

理解 JavaScript 載入機制的同步/非同步特性,是優化首屏渲染、避免阻塞、解決依賴競態的基礎。現代開發應拥抱 defer/async 與 ES Modules,逐步淘汰 document.write 等歷史遺留模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved