<script>
標(biāo)簽用于在HTML
中引入js
,本文主要討論三方面:
- script標(biāo)簽在不同位置引入的區(qū)別(如在head引入和在body引入,在body開頭與最后引入)
- script標(biāo)簽的三種引入方式(default,async,defer),
- script標(biāo)簽?zāi)K化(type='module')
加載與執(zhí)行的區(qū)別
腳本的加載(Loading)與執(zhí)行(Execution)是兩個獨立的概念,它們的行為和影響因素不同,理解這一點對我們后面的討論至關(guān)重要.
- 加載: 瀏覽器從服務(wù)器獲取腳本文件(如
script.js
)的過程,涉及網(wǎng)絡(luò)請求和資源下載。 - 執(zhí)行: 瀏覽器解析并運行腳本中的 JavaScript 代碼。
引入位置區(qū)別
<head>
中引入或在<body>
最開始引入
瀏覽器會暫停 HTML 解析,立即加載并執(zhí)行腳本,執(zhí)行完成后才繼續(xù)解析 DOM。
若腳本體積大或網(wǎng)絡(luò)慢,會導(dǎo)致頁面渲染阻塞(白屏?xí)r間長)。
如果腳本嘗試操作 DOM(如 document.getElementById
),可能因為 DOM 還未解析而找不到元素,導(dǎo)致錯誤。
適用場景
- 需要盡早執(zhí)行且不依賴 DOM 的腳本(如某些性能監(jiān)控、日志上報代碼)。
- 一般不推薦,除非有特殊需求。
<body>
底部引入:
不阻塞 DOM 解析,瀏覽器會先解析完整的 HTML,最后再加載和執(zhí)行腳本,不會影響頁面渲染速度。用戶能更快看到頁面內(nèi)容(減少 FCP,F(xiàn)irst Contentful Paint)。
腳本執(zhí)行時 DOM 已就緒,腳本運行時,整個 DOM 已經(jīng)解析完成,可以安全操作 DOM 元素,無需等待 DOMContentLoaded
事件。
適用場景
- 推薦的經(jīng)典做法,適用于大多數(shù)情況,特別是依賴 DOM 的腳本(如交互邏輯、初始化組件)。
- 如果腳本較大,仍可能影響
DOMContentLoaded
事件觸發(fā)時間。
三種引入
默認(rèn)引入
遵循多個腳本按書寫順序依次加載并執(zhí)行的原則。
defer
<script src="script.js" defer></script>
行為:
- 腳本異步加載(不阻塞 HTML 解析),但會延遲到 DOM 解析完成后、
DOMContentLoaded
事件前按順序執(zhí)行。 - 適用于需要操作 DOM 或依賴其他腳本的場景。
特點:
- 保證腳本的執(zhí)行順序(與書寫順序一致)。
- 天然支持“等 DOM 就緒”,類似
DOMContentLoaded
。
async
<script src="script.js" async></script>
行為:
- 腳本異步加載(不阻塞 HTML 解析),加載完成后立即執(zhí)行(可能中斷 HTML 解析)。
- 適用于獨立腳本(如統(tǒng)計代碼、第三方 SDK)。
特點:
- 不保證執(zhí)行順序(誰先加載完誰先執(zhí)行)。
- 不適合操作 DOM 的腳本(可能 DOM 還未解析完)。
模塊化type="module"
<script type="module" src="module.js"></script>
場景:
行為:
- 避免全局變量污染,依賴關(guān)系清晰,適合大型項目。
- 默認(rèn)具有
defer
行為(異步加載,DOM 解析后執(zhí)行)。 - 若顯式添加
async
(如 <script type="module" async>
),則行為類似 async
。
特點:
- 支持 ES6 模塊語法(
import
/export
)。 - 自動啟用嚴(yán)格模式。
- 模塊腳本默認(rèn)延遲執(zhí)行,且按依賴關(guān)系順序執(zhí)行。
?轉(zhuǎn)自https://juejin.cn/post/7491601352746680383
該文章在 2025/4/12 9:24:04 編輯過