ReviseAlgo Logo

DOM Manipulation

Selecting Elements

Master querying elements in the DOM. Compare getElementById, querySelector, and querySelectorAll in terms of performance and return values.

Last Updated: July 15, 2026 10 min read

1. Introduction

To interact with HTML elements using JavaScript, you must first select them from the DOM tree. The browser provides several APIs for querying nodes, ranging from legacy ID selectors to modern CSS selector matching engines.

2. Why It Matters

Choosing the correct selection method affects both code readability and performance. Knowing the differences between static and live collections prevents bugs where elements appear to be missing or updated unexpectedly.

3. Real-World Analogy

Think of finding Folders in a Filing Cabinet:

  • getElementById: Searching for a folder using a unique barcode ID. You retrieve the folder instantly without needing to scan the rest of the cabinet (highest performance lookup).
  • querySelector: Asking for the "first red folder with an invoice label" (CSS selector). The clerk scans folders until they locate the first match, and stops.
  • querySelectorAll: Asking for "all folders containing unpaid invoices." The clerk scans the entire cabinet, pulls out all matching folders, and returns a static stack (NodeList).

4. Querying APIs

Let's explore the common element selection methods:

1. getElementById:

Queries a single element using its unique id attribute. It is the fastest selection method because the browser keeps a hash index of element IDs.

2. querySelector:

Queries the first element that matches a CSS selector. Returns null if no match is found.

3. querySelectorAll:

Queries all elements matching a CSS selector, returning them in a static NodeList.

5. NodeList vs HTMLCollection (Static vs Live)

Collection Type Returned By Updates dynamically when DOM changes? Supports Array Methods?
HTMLCollection (Live) getElementsByClassName, getElementsByTagName Yes (reflects DOM updates automatically) No (must convert using Array.from)
NodeList (Static) querySelectorAll No (represents a snapshot in time) Partial (supports only forEach)

6. Practical Example

This script illustrates the difference between live and static collections when elements are dynamically added:

7. Common Mistakes

  • Trying to call map or filter on a NodeList directly: NodeList only implements forEach. Attempting to call other array methods throws a TypeError. Convert the NodeList to a true array using Array.from or the spread operator first.
  • Forgetting CSS selector syntax in querySelector: Forgetting the period prefix (.) for class lookups or the hash prefix (#) for ID lookups.

8. Quick Quiz

Q1: Which method returns a live HTMLCollection that updates automatically when the DOM changes?

A) querySelectorAll

B) getElementsByClassName

Answer: B — getElementsByClassName returns a live HTMLCollection, whereas querySelectorAll returns a static NodeList.

9. Scenario-Based Challenge

The Multi-List Filter Utility:

You have a list of cards: querySelectorAll('.card'). You need to filter this list to find only cards containing the class active. Write a clean utility that converts the NodeList to a true array and filters it.

10. Debugging Exercise

Explain why this filter throws a TypeError, and how to fix it:

const cards = document.querySelectorAll('.card');

// Objective: find cards containing the class 'highlight' const highlighted = cards.filter(card => card.classList.contains('highlight')); // crashes!

View Solution

Diagnosis: The querySelectorAll method returns a NodeList, which does not support the filter method on its prototype, throwing a TypeError: cards.filter is not a function.

Fix: Convert the NodeList into a true array before calling filter:

const highlighted = Array.from(cards).filter(card => card.classList.contains('highlight'));

11. Interview Questions

🟢 Q1: Compare getElementById and querySelector in terms of performance and usage.

Answer:
Performance: getElementById is faster because browsers keep a hash index of element IDs, enabling O(1) constant time lookups. querySelector must parse CSS selectors and traverse the DOM tree, resulting in slower lookups.
Usage: getElementById only supports selecting elements by their ID. querySelector supports any valid CSS selector, making it more flexible.

12. Production Considerations

  • Cache Selections: DOM queries are relatively slow. Avoid querying elements repeatedly inside high-frequency event handlers (like scroll or resize listeners); query the elements once and store their references in variables instead.