The Document Object Model (DOM) is a tree-structured programming interface that lets JavaScript read, modify, and respond to a web page's content, structure, and styles in real time.
querySelector/querySelectorAll use CSS selectors and return static results; getElementById returns a single element by ID
textContent sets text safely (no XSS risk); innerHTML parses HTML but is vulnerable to injection with untrusted input
createElement() creates in memory, appendChild()/append() inserts into the DOM, remove() detaches from the DOM
classList.add/remove/toggle/contains for class manipulation; dataset for data-* attributes; setAttribute/getAttribute for others
Batch DOM reads and writes to avoid layout thrashing; use DocumentFragment for bulk insertions; prefer event delegation
The DOM (Document Object Model) is the browser's live, in-memory representation of an HTML document as a tree of objects. JavaScript interacts with the page exclusively through this API — every element, attribute, and text node is an object you can read, create, modify, or remove.
querySelector(selector) returns the first element matching a CSS selector, or null if none found. querySelectorAll(selector) returns a static NodeList of all matches.getElementById(id) returns a single element by its unique ID. Only available on document, not on arbitrary elements.getElementsByClassName and getElementsByTagName return live HTMLCollection objects that update automatically when the DOM changes. Prefer querySelector/querySelectorAll in modern code for consistency and flexibility.NodeList is not an array — it lacks methods like push and map. Convert with Array.from(nodeList) or spread [...nodeList] when you need array methods.textContent gets or sets the text of an element. It is safe against XSS because it does not parse HTML.innerHTML gets or sets the HTML markup inside an element. Setting innerHTML with untrusted input is a security risk (XSS vulnerability). Prefer textContent for plain text.element.setAttribute(name, value) and element.getAttribute(name) read and write HTML attributes. For data attributes, use element.dataset which provides a DOMStringMap of all data-* attributes.element.classList provides add(), remove(), toggle(), and contains() for class manipulation without overwriting existing classes.document.createElement(tag) creates an element in memory — it is not yet in the DOM. You must insert it with parentElement.appendChild(element) or the newer parent.append(element) (which also accepts strings).element.remove() removes an element from the DOM directly. The older pattern parent.removeChild(child) is still widely used.DocumentFragment to build a subtree in memory and insert it in a single operation, avoiding repeated reflows.opacity changes are cheaper than modifying layout properties like width, height, or top.Key Interview Distinction: querySelector vs getElementById
querySelector accepts any CSS selector and works on any element as a scoped search. getElementById only works on document, only matches IDs, but is slightly faster for single-ID lookups. In practice, querySelector is preferred for its flexibility. Interviewers also commonly ask about live vs static collections: getElementsByClassName returns a live HTMLCollection that updates automatically, while querySelectorAll returns a static NodeList that is a snapshot at call time.
Fun Fact
The DOM was not originally designed for dynamic web apps — it was created in the mid-1990s for static document manipulation. The W3C's first DOM specification (Level 1, 1998) didn't even include events. The mismatch between the DOM's document-oriented design and modern app requirements is why frameworks like React, Vue, and Svelte all use abstractions to avoid direct DOM manipulation.