什麼是 JavaScript?

歡迎來到 MDN 初學者 JavaScript 課程!在本文中,我們將從宏觀角度瞭解 JavaScript,回答諸如“它是什麼?”和“你能用它做什麼?”等問題,並確保你對 JavaScript 的目的感到滿意。

預備知識 瞭解 HTMLCSS 基礎知識
學習目標
  • 什麼是 JavaScript,以及它如何融入網站。
  • 你能用 JavaScript 做什麼。
  • 將 JavaScript 新增到網頁中。
  • 在 JavaScript 中編寫註釋。

高階定義

JavaScript 是一種指令碼或程式語言,允許你在網頁上實現複雜的功能——每當網頁不僅僅是靜態地顯示資訊供你檢視時——比如顯示及時內容更新、互動式地圖、動畫 2D/3D 圖形、滾動影片點唱機等——你都可以肯定 JavaScript 可能參與其中。它是標準 Web 技術“分層蛋糕”的第三層,其中兩層(HTMLCSS)我們已經在學習區其他部分更詳細地介紹過。

The three layers of standard web technologies; HTML, CSS and JavaScript

  • HTML 是我們用來構造和賦予 Web 內容意義的標記語言,例如定義段落、標題和資料表,或在頁面中嵌入影像和影片。
  • CSS 是一種樣式規則語言,我們用它來為 HTML 內容應用樣式,例如設定背景顏色和字型,以及將內容佈局成多列。
  • JavaScript 是一種指令碼語言,它使你能夠建立動態更新的內容、控制多媒體、動畫影像以及幾乎所有其他功能。(好吧,不是所有,但你可以用幾行 JavaScript 程式碼實現驚人的效果。)

這三層相互良好地構建。讓我們以一個按鈕為例。我們可以使用 HTML 對其進行標記以賦予其結構和目的

html
<button type="button">Player 1: Chris</button>

Button showing Player 1: Chris with no styling

然後我們可以新增一些 CSS,讓它看起來更漂亮

css
button {
  font-family: "Helvetica Neue", "Helvetica", sans-serif;
  letter-spacing: 1px;
  text-transform: uppercase;
  border: 2px solid rgb(200 200 0 / 60%);
  background-color: rgb(0 217 217 / 60%);
  color: rgb(100 0 0 / 100%);
  box-shadow: 1px 1px 2px rgb(0 0 200 / 40%);
  border-radius: 10px;
  padding: 3px 10px;
  cursor: pointer;
}

Button showing Player 1: Chris with styling

最後,我們可以新增一些 JavaScript 來實現動態行為

js
function updateName() {
  const name = prompt("Enter a new name");
  button.textContent = `Player 1: ${name}`;
}

const button = document.querySelector("button");

button.addEventListener("click", updateName);

你可以點選“播放”在 MDN Playground 中檢視和編輯示例。嘗試點選文字標籤看看會發生什麼。

JavaScript 能做的遠不止這些——讓我們更詳細地探討一下。

注意:在繼續之前,何不現在就動手嘗試 Scrimba 的一項挑戰?檢視 渲染歡迎訊息 MDN 學習夥伴。如果你不知道如何編寫此程式碼,完全不用擔心;你可以嘗試進行一些網路搜尋以找到答案,或者在教程結束時檢視解決方案。

那麼它到底能做什麼?

核心客戶端 JavaScript 語言包含一些常見的程式設計功能,允許你執行以下操作:

  • 將有用的值儲存在變數中。例如,在上面的示例中,我們請求輸入一個新名稱,然後將該名稱儲存在名為 name 的變數中。
  • 對文字片段(在程式設計中稱為“字串”)執行操作。在上面的示例中,我們獲取字串 "Player 1: " 並將其與 name 變數連線起來,以建立完整的文字標籤,例如 "Player 1: Chris"。
  • 響應網頁上發生的某些事件執行程式碼。我們在上面的示例中使用了 click 事件來檢測標籤何時被點選,然後執行更新文字標籤的程式碼。
  • 還有更多!

然而,更令人興奮的是基於客戶端 JavaScript 語言構建的功能。所謂的 應用程式程式設計介面 (API) 為你提供了額外的超能力,可以在你的 JavaScript 程式碼中使用。

API 是一組現成的程式碼構建塊,允許開發人員實現原本難以或不可能實現的程式。它們在程式設計方面所做的事情,就像現成的傢俱套件在房屋建造方面所做的事情一樣——與其自己設計、尋找合適的木材、將所有面板切割成正確的尺寸和形狀、找到正確尺寸的螺絲,然後組裝成一個書架,不如直接使用現成的面板並將它們擰在一起,這樣要容易得多。

它們通常分為兩類。

Two categories of API; 3rd party APIs are shown to the side of the browser and browser APIs are in the browser

瀏覽器 API 內置於你的 Web 瀏覽器中,能夠暴露周圍計算機環境中的資料,或執行有用的複雜操作。例如:

  • DOM(文件物件模型)API 允許你操作 HTML 和 CSS,建立、刪除和更改 HTML,動態地將新樣式應用於你的頁面等等。每當你在頁面上看到彈出窗口出現,或顯示一些新內容(如我們在上面的簡單演示中看到的那樣)時,那就是 DOM 在發揮作用。
  • 地理定位 API 檢索地理資訊。這就是 Google 地圖 能夠找到你的位置並將其繪製在地圖上的方式。
  • CanvasWebGL API 允許你建立動畫 2D 和 3D 圖形。人們正在使用這些 Web 技術做一些令人驚奇的事情——請參閱 Chrome 實驗webglsamples
  • 音訊和影片 API,如 HTMLMediaElementWebRTC,允許你使用多媒體做一些非常有趣的事情,例如直接在網頁中播放音訊和影片,或者從你的網路攝像頭抓取影片並將其顯示在別人的計算機上(嘗試我們的簡單 快照演示 以瞭解其思想)。

第三方 API 預設不內建在瀏覽器中,你通常必須從 Web 上的某個地方獲取它們的程式碼和資訊。例如:

注意:這些 API 是高階的,我們不會在本模組中涵蓋任何這些 API。你可以在我們的客戶端 Web API 模組中找到更多關於它們的資訊。

還有更多可用!然而,不要太興奮。你不會在學習 JavaScript 24 小時後就能構建下一個 Facebook、Google 地圖或 Instagram——首先還有很多基礎知識需要涵蓋。這就是你來這裡的原因——讓我們繼續!

JavaScript 在你的頁面上做什麼?

在這裡,我們將真正開始檢視一些程式碼,同時,探索當你頁面中執行一些 JavaScript 時實際會發生什麼。

讓我們簡要回顧一下瀏覽器載入網頁時發生的事情(首次在我們什麼是 CSS?文章中提到)。當你在瀏覽器中載入網頁時,你正在執行你的程式碼(HTML、CSS 和 JavaScript)在一個執行環境(瀏覽器選項卡)中。這就像一個工廠,接收原材料(程式碼)並輸出產品(網頁)。

HTML, CSS and JavaScript code come together to create the content in the browser tab when the page is loaded

JavaScript 的一個非常常見的用途是,透過文件物件模型 API(如上所述)動態修改 HTML 和 CSS 來更新使用者介面。

瀏覽器安全

每個瀏覽器選項卡都有自己獨立的用於執行程式碼的“儲存桶”(這些儲存桶在技術術語中被稱為“執行環境”)——這意味著在大多數情況下,每個選項卡中的程式碼都是完全獨立執行的,一個選項卡中的程式碼不能直接影響另一個選項卡中的程式碼——或另一個網站。這是一個很好的安全措施——如果不是這樣,那麼駭客可能會開始編寫程式碼從其他網站竊取資訊,以及其他此類壞事。

注意:有方法可以安全地在不同網站/選項卡之間傳送程式碼和資料,但這些是高階技術,我們不會在本課程中介紹。

JavaScript 執行順序

當瀏覽器遇到 JavaScript 程式碼塊時,它通常按從上到下的順序執行。這意味著你需要小心放置內容的順序。例如,讓我們回到我們在第一個示例中看到的 JavaScript 程式碼塊

js
function updateName() {
  const name = prompt("Enter a new name");
  button.textContent = `Player 1: ${name}`;
}

const button = document.querySelector("button");

button.addEventListener("click", updateName);

在這裡,我們首先定義一個名為 updateName() 的程式碼塊(這些可重用程式碼塊被稱為函式),它要求使用者輸入一個新名稱並將該名稱插入到按鈕的文字中。然後我們使用 document.querySelector 儲存對按鈕的引用,並使用 addEventListener 為其附加一個事件監聽器,以便在點選按鈕時,執行 updateName() 函式。

如果你交換 const button = ...button.addEventListener(...) 行的順序,程式碼將不再起作用——相反,你會在瀏覽器開發者控制檯中收到一個錯誤——Uncaught ReferenceError: Cannot access 'button' before initialization。這意味著 button 物件尚未初始化,因此我們無法為其新增事件監聽器。

注意:JavaScript 並非總是完全按照從上到下的順序執行,這取決於像提升這樣的行為,但目前,請記住通常需要在使用之前定義專案。這是錯誤的常見來源。

解釋型程式碼與編譯型程式碼

你可能會在程式設計語境中聽到解釋型編譯型這兩個術語。在解釋型語言中,程式碼從上到下執行,並且程式碼執行的結果會立即返回。你無需在瀏覽器執行程式碼之前將其轉換為不同的形式。程式碼以程式設計師友好的文字形式接收,並直接從該形式進行處理。

另一方面,編譯型語言在由計算機執行之前會被轉換(編譯)成另一種形式。例如,C/C++ 被編譯成機器程式碼,然後由計算機執行。程式從二進位制格式執行,該格式是從原始程式原始碼生成的。

JavaScript 是一種輕量級的解釋型程式語言。Web 瀏覽器接收原始文字形式的 JavaScript 程式碼,並直接從該文字執行指令碼。從技術角度來看,大多數現代 JavaScript 直譯器實際上使用一種稱為即時編譯的技術來提高效能;JavaScript 原始碼在使用時被編譯成更快、二進位制格式,以便儘快執行。然而,JavaScript 仍然被認為是解釋型語言,因為編譯是在執行時處理的,而不是提前處理。

這兩種語言都有優點,但我們現在不會討論它們。

伺服器端程式碼與客戶端程式碼

你可能還會聽到伺服器端客戶端程式碼的術語,尤其是在 Web 開發中。客戶端程式碼是在使用者計算機上執行的程式碼——當檢視網頁時,網頁的客戶端程式碼被下載,然後由瀏覽器執行和顯示。在本模組中,我們明確討論的是客戶端 JavaScript

另一方面,伺服器端程式碼在伺服器上執行,然後其結果被下載並顯示在瀏覽器中。流行的伺服器端 Web 語言示例包括 PHP、Python、Ruby、C#,甚至是 JavaScript!JavaScript 也可以用作伺服器端語言,例如在流行的 Node.js 環境中——你可以在我們的動態網站 – 伺服器端程式設計主題中找到更多關於伺服器端 JavaScript 的資訊。

動態程式碼與靜態程式碼

動態這個詞用於描述客戶端 JavaScript 和伺服器端語言——它指的是根據不同情況更新網頁/應用程式顯示不同內容的能力,按需生成新內容。伺服器端程式碼在伺服器上動態生成新內容,例如從資料庫中提取資料,而客戶端 JavaScript 在客戶端的瀏覽器中動態生成新內容,例如建立新的 HTML 表格,用從伺服器請求的資料填充它,然後將表格顯示在呈現給使用者的網頁中。這兩種含義在兩個上下文中略有不同,但相關聯,並且兩種方法(伺服器端和客戶端)通常協同工作。

沒有動態更新內容的網頁被稱為靜態——它總是顯示相同的內容。

如何將 JavaScript 新增到你的頁面?

JavaScript 以類似於 CSS 的方式應用於你的 HTML 頁面。CSS 使用 <link> 元素來應用外部樣式表,並使用 <style> 元素來應用內部樣式表到 HTML,而 JavaScript 在 HTML 世界中只需要一個朋友——<script> 元素。讓我們瞭解這是如何工作的。

注意:Scrimba 的設定我們的 JavaScript 檔案MDN 學習夥伴互動式教程演示了幾種將 JavaScript 新增到 HTML 的不同方法。

內部 JavaScript

  1. 首先,將我們的示例檔案 apply-javascript.html 建立一個本地副本。將其儲存到某個合適的目錄中。

  2. 在你的網頁瀏覽器和文字編輯器中開啟該檔案。你會看到 HTML 建立了一個包含一個可點選按鈕的簡單網頁。

  3. 接下來,轉到你的文字編輯器,在你的 body 底部——緊靠在結束的 </body> 標籤之前新增以下內容

    html
    <script>
      // JavaScript goes here
    </script>
    

    請注意,你的 Web 文件中的程式碼通常按照它們在頁面上出現的順序載入和執行。透過將 JavaScript 放在底部,我們確保所有 HTML 元素都已載入。(另請參閱下面的指令碼載入策略。)

  4. 現在我們將在 <script> 元素中新增一些 JavaScript,使頁面做一些更有趣的事情——在 "// JavaScript goes here" 行下方新增以下程式碼

    js
    function createParagraph() {
      const para = document.createElement("p");
      para.textContent = "You clicked the button!";
      document.body.appendChild(para);
    }
    
    const buttons = document.querySelectorAll("button");
    
    for (const button of buttons) {
      button.addEventListener("click", createParagraph);
    }
    
  5. 儲存檔案並重新整理瀏覽器——現在你應該會看到,當你點選按鈕時,會生成一個新的段落並放置在下方。

注意:如果你的示例似乎不起作用,請再次檢查步驟,確保你做得一切正確。你是否將起始程式碼的本地副本儲存為 .html 檔案?你是否將 <script> 元素新增到 </body> 標籤之前?你是否精確輸入了 JavaScript,如所示?JavaScript 對大小寫敏感,並且非常挑剔,因此你需要精確輸入語法,否則它可能無法工作。

注意:你可以在 GitHub 上看到此版本,名為 apply-javascript-internal.html也可線上檢視)。

外部 JavaScript

這很好,但如果我想把 JavaScript 放在一個外部檔案中呢?讓我們現在探討一下。

  1. 首先,在與你的示例 HTML 檔案相同的目錄中建立一個新檔案。將其命名為 script.js——確保它具有 .js 檔名副檔名,因為這是識別其為 JavaScript 的方式。

  2. 刪除 </body> 底部當前的 <script> 元素,並在結束的 </head> 標籤之前新增以下內容(這樣瀏覽器可以比在底部時更早地開始載入檔案)

    html
    <script type="module" src="script.js"></script>
    
  3. script.js 內部,新增以下指令碼

    js
    function createParagraph() {
      const para = document.createElement("p");
      para.textContent = "You clicked the button!";
      document.body.appendChild(para);
    }
    
    const buttons = document.querySelectorAll("button");
    
    for (const button of buttons) {
      button.addEventListener("click", createParagraph);
    }
    
  4. 儲存並重新整理瀏覽器。你會發現點選按鈕沒有效果,如果你檢查瀏覽器的控制檯,你會看到類似 Cross-origin request blocked 的錯誤。這是因為像許多外部資源一樣,JavaScript 模組需要從與 HTML 同源載入,而 file:// URL 不符合要求。有兩種解決方案可以解決這個問題

    • 我們推薦的解決方案是設定本地測試伺服器。執行伺服器程式並在埠 8000 上提供 apply-javascript-external.htmlscript.js 檔案後,開啟瀏覽器並訪問 https://:8000
    • 如果無法執行本地伺服器,也可以使用 <script defer src="script.js"></script> 而不是 <script type="module" src="script.js"></script>。有關更多資訊,請參閱下面的指令碼載入策略。但請注意,教程其他部分使用的功能可能仍需要本地 HTTP 伺服器。
  5. 現在網站和以前一樣工作,但現在我們的 JavaScript 放在一個外部檔案中。這通常在組織程式碼和使其在多個 HTML 檔案中可重用方面是件好事。此外,HTML 更容易閱讀,沒有大量指令碼堆積其中。

注意:你可以在 GitHub 上看到此版本,名為 apply-javascript-external.htmlscript.js也可線上檢視)。

內聯 JavaScript 處理程式

請注意,有時你會遇到實際的 JavaScript 程式碼在 HTML 中。它可能看起來像這樣

js
function createParagraph() {
  const para = document.createElement("p");
  para.textContent = "You clicked the button!";
  document.body.appendChild(para);
}
html
<button onclick="createParagraph()">Click me!</button>

你可以在下面嘗試我們這個演示版本。

這個演示與前兩節的功能完全相同,不同之處在於 <button> 元素包含一個內聯的 onclick 處理程式,以便在按鈕按下時執行函式。

然而,請不要這樣做。用 JavaScript 汙染 HTML 是一種不好的做法,而且效率低下——你必須在每個你希望 JavaScript 應用的按鈕上都包含 onclick="createParagraph()" 屬性。

改為使用 addEventListener

不要將 JavaScript 包含在 HTML 中,而是使用純 JavaScript 結構。querySelectorAll() 函式允許你選擇頁面上的所有按鈕。然後你可以遍歷按鈕,使用 addEventListener() 為每個按鈕分配一個處理程式。程式碼如下所示

js
const buttons = document.querySelectorAll("button");

for (const button of buttons) {
  button.addEventListener("click", createParagraph);
}

這可能比 onclick 屬性稍微長一些,但它適用於所有按鈕——無論頁面上有多少個,也無論新增或刪除了多少個。JavaScript 不需要更改。

注意:嘗試編輯你的 apply-javascript.html 版本,並在檔案中新增更多按鈕。當你重新載入時,你會發現點選所有按鈕都會建立一個段落。很棒,對吧?

指令碼載入策略

頁面上的所有 HTML 都按照它們出現的順序載入。如果你使用 JavaScript 來操縱頁面上的元素(或者更準確地說,是文件物件模型),如果 JavaScript 在你嘗試操作的 HTML 之前載入和解析,你的程式碼將無法工作。

有幾種不同的策略可以確保你的 JavaScript 僅在 HTML 被解析後執行

  • 在上面的內部 JavaScript 示例中,指令碼元素放置在文件主體的底部,因此僅在 HTML 主體的其餘部分解析後才執行。

  • 在上面的外部 JavaScript 示例中,指令碼元素放置在文件的頭部,在 HTML body 解析之前。但是因為我們使用的是 <script type="module">,程式碼被視為一個模組,瀏覽器會等待所有 HTML 處理完畢後才執行 JavaScript 模組。(你也可以將外部指令碼放在 body 底部。但是,如果 HTML 很多且網路緩慢,瀏覽器甚至可能需要很長時間才能開始獲取和載入指令碼,因此將外部指令碼放在 head 中通常更好。)

  • 如果你仍然想在文件頭中使用非模組指令碼,這可能會阻止整個頁面顯示,並可能因為在 HTML 解析之前執行而導致錯誤

    • 對於外部指令碼,你應該在 <script> 元素上新增 defer(或者如果你不需要 HTML 準備就緒,則新增 async)屬性。
    • 對於內部指令碼,你應該將程式碼封裝在 DOMContentLoaded 事件監聽器中。

    這一點超出了本教程的範圍,但是除非你需要支援非常舊的瀏覽器,否則你不必這樣做,只需使用 <script type="module"> 即可。

註釋

與 HTML 和 CSS 一樣,你可以在 JavaScript 程式碼中編寫註釋,這些註釋將被瀏覽器忽略,其作用是向你的同事開發人員(以及你,如果你在六個月後回來檢視程式碼並且不記得你做了什麼)提供關於程式碼如何工作的說明。註釋非常有用,你應該經常使用它們,特別是對於大型應用程式。有兩種型別

  • 單行註釋寫在雙斜槓 (//) 之後,例如

    js
    // I am a comment
    
  • 多行註釋寫在 /**/ 字串之間,例如

    js
    /*
      I am also
      a comment
    */
    

例如,我們可以這樣用註釋來註解我們上一個演示的 JavaScript

js
// Function: creates a new paragraph and appends it to the bottom of the HTML body.

function createParagraph() {
  const para = document.createElement("p");
  para.textContent = "You clicked the button!";
  document.body.appendChild(para);
}

/*
  1. Get references to all the buttons on the page in an array format.
  2. Loop through all the buttons and add a click event listener to each one.

  When any button is pressed, the createParagraph() function will be run.
*/

const buttons = document.querySelectorAll("button");

for (const button of buttons) {
  button.addEventListener("click", createParagraph);
}

注意:一般來說,註釋越多越好,但如果你發現自己添加了大量註釋來解釋變數(你的變數名可能應該更直觀),或者解釋非常簡單的操作(也許你的程式碼過於複雜),那麼你應該小心。

總結

就這樣,你邁出了進入 JavaScript 世界的第一步。我們從理論開始,讓你習慣於為什麼以及如何使用 JavaScript。在此過程中,你看到了幾個程式碼示例,並瞭解了 JavaScript 如何與你網站上的其他程式碼協同工作,等等。

JavaScript 現在可能看起來有點令人生畏,但別擔心——在本課程中,我們將透過簡單的步驟帶你學習,這些步驟將讓你循序漸進。在下一篇文章中,我們將直接進入實踐,讓你立即動手構建自己的 JavaScript 示例。