script 標籤


要在瀏覽器中執行 JavaScript,可在一個 HTML 檔案中撰寫 <script></script>,並於兩個標籤間撰寫 JavaScript 程式碼。例如:

<script>
    let name = prompt('Input your name');
    alert(`Hello! ${name}!`);
</script>

按此看執行結果

上例中,promptalert 是瀏覽器上全域物件上提供的函式,在瀏覽器中,全域物件就是 window 物件,代表瀏覽器本身,為 Window 的實例。當然,上面的 JavaScript 程式沒什麼作用,只是讓你輸入名稱並顯示而已。你可以將 <script></script> 放在 HTML 標籤之中。例如:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
</head>
<body>
      JavaScript Example!<br>
      <script>
          let name = prompt('Input your name');
          document.write(`Hello! ${name}!`);
      </script><br>
      JavaScript Example!
</body>
</html>

按此看執行結果

預設情況下,瀏覽器在遇到 <script></script> 時,會停止文件解析,先執行 <script></script> 間的JavaScript,documentwindow 全域物件上的特性,代表整份 HTML 文件,為 Document 的實例。如果執行 documentwrite() 方法,則會在 <body> 中目前文件解析點輸出指定的文字,執行完 <script></script> 間的 JavaScript 後,再繼續文件的解析。

基本上,瀏覽器會假設你使用的是 JavaScrip t語言,不過也可以用 HTTP Content-Script-Type 標頭來指定,標頭可以使用 <meta> 來摸擬,所以可以如下指定:

<meta http-equiv="Content-Script-Type" content="text/javascript">

也可以在 <script> 上使用 type 屬性來指定。例如:

<script type="text/javascript">
    // 你的程式碼
</script>

type 指定可以是 MIME(Multipurpose Internet Mail Extension)型態,一些可指定的範例有:

  • text/javascript
  • text/ecmascript
  • application/javascript
  • text/jscript
  • text/vbscript

第一個是 JavaScript 的官方名稱,其它類型的指定,主要是看瀏覽器是否支援,例如在安裝 IronPython 的情況下,甚至可以讓 Internet Explorer 支援 text/python 的指定。

HTML4 規範了 type 屬性,但在 HTML5 中為選用。在早期,<script> 上還允許設定 language 屬性,在 HTML 4 時標準化 <script> 標籤時,並沒有採納 language 屬性,有時會有一些早期撰寫的網頁上看到這樣的設定:

<script language="javascript">
    // 你的程式碼
</script>

language 甚至也允許撰寫版本號,例如:

<script language="javascript1.2">
    // 你的程式碼
</script>

由於 HTML 4 並沒有採納 language,現在已不建議設定,新版瀏覽器也會忽略這個屬性,僅有時為了與舊版瀏覽器相容,你會看到這樣的設定:

<script type="text/javascript" language="javascript">
    // 你的程式碼
</script>

可以將 <script></script> 放在整份 HTML 文件之後,</body> 之前,依照現在的最佳實踐來說,應該這麼做,因為 HTML 文件此時已經載入、剖析完成,應有的 DOM 元素也已經產生,若 JavaScript 必須操作 DOM 元素,此時可以放心地進行操作。

也可以將 <script></script> 放在 <head></head> 之間,過去瀏覽器上的 JavaScript 程式碼,經常是這麼做的。例如:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script type="text/javascript">
        let name = prompt('Input your name');
        document.write(`Hello! ${name}`);
    </script>
</head>
<body>
    JavaScript Example!
</body>
</html>

按此看執行結果

要注意的是,瀏覽器處理 <head></head> 間的JavaScript時,還沒有解析 <body> 中的標籤,所以上例中,documentwrite 會直接從 <body> 的第一行開始。一般初學者常犯的錯誤是:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script type="text/javascript">
        let welcome = document.getElementById('welcome');
        welcome.innerHTML = `Hello! ${prompt('Input your name')}!`;
    </script>
</head>
<body>
    <span id="welcome"></span>
</body>
</html>

按此看執行結果

documentgetElementById 可以根據 HTML 標籤的 id 屬性值取得 HTML 標籤的 DOM 物件,innerHTML 可設定實例的 HTML 內容(innerHTML 在 HTML5 中是標準特性)。在執行上例的 JavaScript 時,<body></body> 中的文件根本還沒開始解析,所以 <span id="welcome"></span> 根本還不存在,所以取得的是 undefined,根本無從設定 innerHTML,若是將上例中的 <script> 程式碼移至 </body>
之前,就不會有這個問題。

要等到全部文件資源完整載入後再執行指定的程式碼,也可以借助 window.onload 事件。例如:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script type="text/javascript">
        window.onload = function() {
            let welcome = document.getElementById('welcome');
            welcome.innerHTML = `Hello! ${prompt('Input your name')}!`;
        };
    </script>
</head>
<body>
    <span id="welcome"></span>
</body>
</html>

按此看執行結果

window 物件的 onload 特性可以指定函式,當瀏覽器完成整份文件資源的載入後,如果 onload 特性有設定函式,就會予以呼叫,然而,完成整份文件資源的載入是指 HTML、CSS、圖片等都被載入完成,而不是單指是 DOM 樹建立完成,因此,如果文件資源非常的多,或者是網路速度不佳,那麼在可以執行 JavaScript 的效果之前,訪客看到的可能會是不完整的使用者介面。

可以將 JavaScript 程式撰寫在 .js 檔案中,並使用 <script>src 屬性指定檔案名稱。例如,將底下的程式寫在一個 hello.js:

window.onload = function() {
    let welcome = document.getElementById('welcome');
    welcome.innerHTML = `Hello! ${prompt('Input your name')}!`;
};

如果上面的 .js 檔案放在 js 資料夾中,則可以如下使用:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script type="text/javascript" src="js/hello.js"></script>
</head>
<body>
    <span id="welcome"></span>
</body>
</html>

按此看執行結果(在 JS Bin 中,只要寫在 JavaScript 頁框中的程式碼,會自動嵌入 HTML 之中)。

雖然程式都在 .js 中,但 <script></script> 還是要成對出現,而 <script></script> 中出現的程式碼會被忽略。

在這邊要注意編碼的問題,瀏覽器會假設載入的 .js 檔案編碼與 HTML 網頁編碼相同。如果 .js 檔案編碼與 HTML 編碼不同,JavaScript 中非 ASCII 相容字元部份就會出現亂碼。

例如,如果 .js 是 Big5 編碼,而網頁是 UTF-8 顯示,則可以在 <script> 上使用 charset 指定 .js 的編碼為 Big5:

<script type="text/javascript" charset="Big5" src="js/hello.js"></script>

預設情況下,瀏覽器會同步地下載 .js 檔案,直到 .js 下載完成,並執行完內容之前,後續的其他資源下載、頁面剖析等都會被阻斷。

可以在 <script> 加上 async 屬性,如此瀏覽器會以非同步方式下載 .js 檔案,在 .js 下載完成前,不會阻斷後續資源的下載與頁面剖析,然而 .js 下載完成後,瀏覽器會暫停其他資源下載或頁面剖析,先執行該 .js 的內容後,再繼續處理其他資源下載或頁面剖析,如果有多個 async 屬性的 .js,執行的順序是無法預期的。

可以在 <script> 加上 defer 屬性,如此瀏覽器會以非同步方式下載 .js 檔案,.js 就算下載完成,也不會馬上執行,而是在 DOM 樹生成與其他非 defer 的 .js 執行完後,才執行被加上 defer 屬性的 .js,如果有多個 defer 屬性的 .js,那麼按照它們在頁面上出現的順序執行。

現在不支援 JavaScript 的瀏覽器幾不存在,不過瀏覽器上的 JavaScript 仍可能因一些原因無法使用(例如防毒軟體、安全機制等級,或者是爬蟲程式之類)。如果想在無法執行 JavaScript 時,仍可呈現一些基本功能畫面,則可以使用 <noscript></noscript>,夾雜在 <noscript></noscript> 中的內容,會在無法執行 JavaScript 時出現,為使用者提供替代的頁面內容。

有些瀏覽器或爬蟲無法執行 JavaScript,此時會使用 <!----> 註解,讓這些它們看不到 JavaScript 程式碼:

<script type="text/javascript">
<!--

    // 你的程式...

//-->
</script>

瀏覽器作為客戶端的時候作了些調整,讓 <!-- 的作用如同 JavaScript 的 // 單行註解,所以 <!-- 不會發生執行錯誤,而 --> 前的 // 因為是單行註解,所以就看不到之後的 --> 了。