什麼是 JavaScript?

歡迎來到 MDN JavaScript 初學者課程! 在本文中,我們將從更高的層次瞭解 JavaScript,回答諸如“它是什麼?”和“你能用它做什麼?”之類的問題,並確保您對 JavaScript 的用途感到滿意。

先決條件 對 HTML 和 CSS 的基本瞭解。
目標 熟悉 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
const button = document.querySelector("button");

button.addEventListener("click", updateName);

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

嘗試單擊文字標籤的最後一個版本,看看會發生什麼(還要注意,您可以在 GitHub 上找到此演示——檢視 原始碼,或 線上執行)!

JavaScript 可以做的不僅僅是這些——讓我們更詳細地探討一下。

它到底能做什麼?

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

  • 將有用的值儲存在變數中。例如,在上面的示例中,我們要求輸入一個新的姓名,然後將該姓名儲存在名為 name 的變數中。
  • 對文字片段(在程式設計中稱為“字串”)進行操作。在上面的示例中,我們將字串“玩家 1:”與 name 變數連線起來,建立完整的文字標籤,例如“玩家 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)允許您對多媒體做一些非常有趣的事情,例如在網頁中播放音訊和影片,或者從您的網路攝像頭獲取影片並在其他人的計算機上顯示它(嘗試我們簡單的 Snapshot 演示,瞭解一下)。

**注意:** 上述許多演示在較舊的瀏覽器中將無法正常工作——在進行實驗時,最好使用現代瀏覽器(如 Firefox、Chrome、Edge 或 Opera)來執行您的程式碼。在您更接近交付生產程式碼時(即真正的客戶將使用的真實程式碼),您將需要更詳細地考慮 跨瀏覽器測試

**第三方 API** 預設情況下不會內建到瀏覽器中,您通常需要從 Web 上的某個地方獲取它們的程式碼和資訊。例如

**注意:** 這些 API 很高階,我們不會在本模組中介紹任何這些 API。您可以在我們的 客戶端 Web API 模組 中找到更多有關這些 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
const button = document.querySelector("button");

button.addEventListener("click", updateName);

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

在這裡,我們首先使用 document.querySelector 選擇一個按鈕,然後使用 addEventListener 為其附加一個事件監聽器,以便當單擊按鈕時,執行 updateName() 程式碼塊(第 5-8 行)。updateName() 程式碼塊(這些型別的可重用程式碼塊稱為“函式”)詢問使用者一個新的姓名,然後將該姓名插入按鈕文字中以更新顯示。

如果您交換前兩行程式碼的順序,它將不再起作用——相反,您將在 瀏覽器開發者控制檯 中收到一個錯誤——未捕獲的 ReferenceError:在初始化之前無法訪問 'button'。這意味著 button 物件尚未初始化,因此我們無法為其新增事件監聽器。

**注意:** 這是一個非常常見的錯誤——您需要確保程式碼中引用的物件在您嘗試對它們執行操作之前存在。

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

您可能會在程式設計上下文中聽到 **解釋型** 和 **編譯型** 術語。在解釋型語言中,程式碼從上到下執行,執行程式碼的結果立即返回。您不必將程式碼轉換為另一種形式,然後瀏覽器才能執行它。程式碼以程式設計師友好的文字形式接收,並直接從該形式進行處理。

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

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

兩種型別的語言都有優點,但我們現在不討論它們。

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

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

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

動態程式碼與靜態程式碼

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

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

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

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

內部 JavaScript

  1. 首先,製作示例檔案apply-javascript.html的本地副本。將其儲存在某個合理的目錄中。
  2. 在你的 Web 瀏覽器和文字編輯器中開啟檔案。你會看到 HTML 建立了一個包含可點選按鈕的簡單網頁。
  3. 接下來,轉到你的文字編輯器,並將以下內容新增到你的 body 底部——就在你的結束</body>標籤之前
    html
    <script>
      // JavaScript goes here
    </script>
    
    請注意,你的 Web 文件中的程式碼通常按照它在頁面上出現的順序載入和執行。透過將 JavaScript 放置在底部,我們確保所有 HTML 元素都已載入。(另請參閱下面指令碼載入策略。)
  4. 現在,我們將新增一些 JavaScript 程式碼到我們的<script>元素中,使頁面做一些更有趣的事情——將以下程式碼新增到 "// 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檔案?你是否在</body>標籤之前添加了你的<script>元素?你是否完全按照所示輸入了 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 中,HTML 更易於閱讀。

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

內聯 JavaScript 處理程式

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

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處理程式,以便在按下按鈕時執行該函式。

但是,請不要這樣做。在 HTML 中使用 JavaScript 程式碼是一種不好的做法,而且效率低下——你必須在要應用 JavaScript 程式碼的每個按鈕上包含onclick="createParagraph()"屬性。

使用 addEventListener 替代

不要在 HTML 中包含 JavaScript 程式碼,而是使用純 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 示例中,指令碼元素被放置在文件 body 的底部,因此只有在解析完其餘的 HTML body 後才會執行。
  • 在上面的外部 JavaScript 示例中,指令碼元素被放置在文件 head 中,在解析 HTML body 之前。但由於我們使用的是<script type="module">,因此程式碼被視為一個模組,並且瀏覽器會在執行 JavaScript 模組之前等待所有 HTML 程式碼被處理。(你也可以將外部指令碼放置在 body 的底部。但如果 HTML 程式碼很多,網路很慢,那麼瀏覽器可能需要很長時間才能開始獲取和載入指令碼,因此將外部指令碼放在 head 中通常更好。)
  • 如果你仍然想在文件 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 示例。