script 標籤與模組
September 9, 2022網頁透過 script
標籤來定義 JavaScript 程式碼,若瀏覽器支援,可以將 type
屬性設定為 "module"
,表示內嵌或引用的 .js 程式碼是 ES6 模組。例如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="module">
let welcome = document.getElementById('welcome');
let name = prompt('輸入你的名稱');
welcome.innerHTML = `哈囉!${name}!`;
</script>
</head>
<body>
<span id="welcome"></span>
</body>
</html>
引用模組
當 type
設定為 "module"
時,script
內嵌或透過 src
引用 .js 時,預設具有 defer
的特性,也就是 .js 會以非同步方式下載,並在 DOM 樹生成與其他非 defer
的 .js 執行完後,才依頁面出現順序執行 defer的程式碼,因此,上例的
script雖然寫在
head標籤中,也是在 DOM 樹生成後執行 。 當
type設定為
“module” 時,
src` 引用的 .js 就視為模組,例如,若 hello.js 如下定義:
let welcome = document.getElementById('welcome');
let name = prompt('輸入你的名稱');
welcome.innerHTML = `哈囉!${name}!`;
引用模組時,.js 不能來自本機,因此得啟動一個 HTTP 伺服器,才能如下引用模組:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="module" src="mods/hello2.js"></script>
</head>
<body>
<span id="welcome"></span>
</body>
</html>
可見性
每個模組中的定義的名稱,僅在模組內可見,script
標籤的 type
設為 "module"
時,就代表著一個模組,內嵌的程式碼也是一個模組,其他 script
看不到其中的名稱。例如以下會發生錯誤:
<script type="module">
// hello僅在此模組可見
function hello(name) {
return `Hello! ${name}!`;
}
</script>
<script type="text/javascript">
console.log(hello('Justin')); // ReferenceError
</script>
就算兩個 script
標籤的 type
設為 "module"
時,各自的名稱也是互不相見,以下也是會發生錯誤:
<script type="module">
// hello僅在此模組可見
function hello(name) {
return `Hello! ${name}!`;
}
</script>
<script type="module">
console.log(hello('Justin')); // ReferenceError
</script>
標籤的 type
設為 "module"
並引用外部模組時,可以附加 async
屬性,此時會非同步下載 .js 檔案,先下載完成就先執行。
降級處理
支援模組的瀏覽器,會忽略 <script nomodule></script>
,因此對於打算提供降級處理的情境,可以如下撰寫:
<script type="module" src="mods/util.js"></script>
<script nomodule src="js/util_fallback.js"></script>
支援模組的瀏覽器會使用 util.js,忽略 <script nomodule></script>
;不支援模組的瀏覽器,本來就不理會 type
設為 module
的 script
標籤,因此會使用 util_fallback.js。