本文 AI 產出,尚未審核

JavaScript – DOM 與瀏覽器 API

單元:文件選取(querySelector / getElementById


簡介

在前端開發中,DOM(Document Object Model) 是連結 HTML 文件與 JavaScript 程式碼的橋樑。只有正確、快速地取得想操作的元素,才能實現動態 UI、表單驗證、動畫效果等各種互動功能。
querySelectorgetElementById 是最常使用的兩種選取方法,前者支援 CSS 選擇器,彈性極高;後者則只針對 id,在已知唯一標識時速度最快。了解兩者的差異、使用時機與最佳實踐,對於從 初學者 逐步成長為 中階開發者 相當關鍵。

本篇文章將從概念說明、實作範例、常見陷阱以及實務應用等面向,完整介紹這兩個 API,讓你在開發中能夠 快速定位元素、降低錯誤、提升效能


核心概念

1. getElementById – 直接以 ID 取元素

  • 語法document.getElementById(id)
  • 傳回值:若找到相符的元素,回傳 單一 HTMLElement;找不到則回傳 null
  • 特性
    • 只接受 字串 型別的 id
    • 因為 HTML 中的 id 必須唯一,瀏覽器在內部使用 哈希表(hash table)快速定位,效能最佳。
    • 不支援 CSS 選擇器語法(例如 .class[type="text"])。

小提醒id 必須符合 HTML 規範(不能以數字開頭、不能有空白),否則 getElementById 仍會回傳元素,但會影響 CSS 與其他 API 的行為。

2. querySelector – 用 CSS 選擇器選取單一元素

  • 語法document.querySelector(selector)
  • 傳回值:符合 第一個(最左側)匹配的元素;找不到則回傳 null
  • 特性
    • 接受任意合法的 CSS 選擇器(ID、class、屬性、階層、偽類…)。
    • 只會回傳 第一筆匹配結果,若想取得全部符合的元素,需使用 querySelectorAll
    • 在大型文件中,瀏覽器會先執行 selector engine(如 Sizzle)解析,效能稍遜於 getElementById,但差距在現代瀏覽器已相當小。

3. 為什麼同時提供兩種 API?

  • 彈性 vs 效能querySelector 為開發者提供了類似 CSS 的寫法,讓代碼更具可讀性;getElementById 則在已知唯一 ID 時提供最快的存取。
  • 語意清晰:使用 getElementById 能明確表達「我只需要這個唯一元素」,有助於程式碼自說明(self‑documenting)。
  • 相容性getElementById 自 IE4 起就支援;querySelector 於 IE8+(IE9+ 完整支援)才加入,現在已是所有主流瀏覽器的標準。

程式碼範例

以下示範 5 個實用案例,說明兩者在不同情境下的使用方式與注意點。

範例 1️⃣:最基本的 ID 取得(getElementById

<!-- index.html -->
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
  <meta charset="UTF-8">
  <title>getElementById 範例</title>
</head>
<body>
  <h1 id="title">Hello World</h1>
  <script>
    // 直接取得 id 為 title 的 <h1> 元素
    const titleEl = document.getElementById('title');
    // 改變文字內容
    titleEl.textContent = '你好,JavaScript!';
  </script>
</body>
</html>

重點getElementById 回傳的就是 <h1>,不需要再做型別斷言(TypeScript 中會自動推斷為 HTMLElement)。


範例 2️⃣:使用 CSS 選擇器取得第一個符合的元素(querySelector

<div class="card">
  <p class="desc">第一段描述</p>
</div>
<div class="card">
  <p class="desc">第二段描述</p>
</div>

<script>
  // 只會拿到第一個 .card 裡面的 .desc
  const firstDesc = document.querySelector('.card .desc');
  console.log(firstDesc.textContent); // => "第一段描述"
</script>

說明.card .desc 是「在 .card 內部的 .desc」的階層選擇器,querySelector 只回傳第一筆匹配結果。


範例 3️⃣:結合 querySelector 與屬性選擇器

<input type="text" name="username" placeholder="使用者名稱">
<input type="password" name="password" placeholder="密碼">

<script>
  // 取得 name 為 password 的 <input>
  const pwdInput = document.querySelector('input[name="password"]');
  // 設定預設值(僅示範,實務上不建議明文寫入)
  pwdInput.value = '123456';
</script>

技巧:屬性選擇器可以讓你不必依賴 idclass,在表單大量相似元素時特別有用。


範例 4️⃣:使用 getElementById 取得表單元素並監聽事件

<form id="loginForm">
  <input id="user" type="text" placeholder="帳號">
  <input id="pwd" type="password" placeholder="密碼">
  <button type="submit">登入</button>
</form>

<script>
  const form = document.getElementById('loginForm');
  const userInput = document.getElementById('user');
  const pwdInput = document.getElementById('pwd');

  form.addEventListener('submit', function (e) {
    e.preventDefault(); // 防止表單真的送出
    alert(`帳號:${userInput.value}\n密碼:${pwdInput.value}`);
  });
</script>

最佳實踐:表單內的每個欄位都使用唯一 id,配合 getElementById,讓程式碼在閱讀時一眼就能看出「哪個欄位」在被操作。


範例 5️⃣:動態產生元素後再使用 querySelector 取得

<div id="container"></div>

<script>
  // 動態建立一個 <ul>,裡面有三個 <li>
  const ul = document.createElement('ul');
  ul.innerHTML = `
    <li class="item">項目 A</li>
    <li class="item">項目 B</li>
    <li class="item">項目 C</li>
  `;
  document.getElementById('container').appendChild(ul);

  // 立即使用 querySelector 取得第一個 .item
  const firstItem = document.querySelector('#container .item');
  firstItem.style.color = 'tomato';
</script>

要點:即使元素是 動態插入 的,只要在插入完成之後呼叫 querySelector,仍能正確取得。若在插入前呼叫,會得到 null


常見陷阱與最佳實踐

陷阱 說明 解決方案/最佳實踐
1. 使用錯誤的選擇器語法 getElementById('#myId') 會因為多了 # 而找不到元素。 getElementById('myId')(不加 #
2. 多個相同 ID HTML 允許重複 ID,會導致 getElementById 只回傳第一個,其他元素無法被選取。 確保 全站唯一,若需要多個相同標記,改用 classdata- 屬性。
3. 過度使用 querySelectorAll 再取第一筆 有時開發者寫 document.querySelectorAll('.item')[0],其實可以直接用 querySelector('.item'),省去陣列建立與索引的開銷。 若只需要第一筆,直接使用 querySelector
4. 在元素未載入前就執行選取 若腳本放在 <head>,DOM 尚未完成解析,getElementById / querySelector 會回傳 null 把腳本放在 body 結尾,或使用 DOMContentLoaded 事件:
document.addEventListener('DOMContentLoaded', () => { /* 選取程式 */ });
5. 依賴過於複雜的 CSS 選擇器 過長的選擇器(如 div > ul > li > a.active) 會降低效能,且在結構變動時易斷裂。 盡量使用 簡潔且具意義的 class / id,必要時加上 data- 屬性作為選取依據。

效能小技巧

  1. 優先使用 getElementById:在已知唯一 ID 時,直接使用 getElementById,效能約比 querySelector('#id') 高 2–3 倍。
  2. 避免過度遍歷:若需要在大量元素中搜尋,先限定範圍(如 section.querySelector)再進行搜尋,可減少整份文件的遍歷成本。
  3. 快取選取結果:同一元素會被多次使用時,先存入變數,避免重複呼叫 API。

實際應用場景

場景 建議使用的選取方式 為什麼
表單驗證 getElementById 針對每個欄位的 id 每個欄位唯一,易於維護且效能佳。
動態列表(如新聞、商品) querySelectorAll('.list-item') 配合 forEach 需要一次取得全部項目,並逐一處理。
單頁應用(SPA)路由切換 querySelector('#app') + querySelector('.view.active') 只需定位根容器與目前顯示的視圖。
模態視窗/彈出層 document.querySelector('[data-modal="login"]') 使用 data- 屬性避免 id 重複,且語意清晰。
CSS 動畫觸發 document.querySelector('.animate-target') 透過 class 選擇器快速取得目標,配合 classList.add() 觸發動畫。

總結

  • getElementById:最快、最直接的單一元素取得方式,適用於 唯一 ID 的情境。
  • querySelector:彈性十足的 CSS 選擇器,能一次解決多種選取需求,但在大量元素或頻繁呼叫時需留意效能。
  • 最佳實踐
    1. 先思考 元素的唯一性,若唯一則優先 getElementById
    2. 若需要階層、屬性或多條件篩選,使用 querySelector(或 querySelectorAll)。
    3. 確保腳本執行時 DOM 已完成解析,避免 null
    4. 盡量使用 語意清晰的 class / data-屬性 來作為選取依據,提升可讀性與維護性。

掌握這兩個核心 API,你就能在 DOM 操作 上游刃有餘,無論是簡單的表單互動或是複雜的單頁應用,都能以最直觀、最有效率的方式取得目標元素。祝你寫程式寫得開心,專案順利上線! 🚀