DOMbeginner
DOM Manipulation Basics
Selecting, creating, modifying, and removing elements from the live document tree using core DOM APIs.
The DOM is the live tree of the page. Changing it changes what the user sees, immediately.
The DOM is like a building's live floor plan blueprint that also happens to be the actual building — walking up and modifying a wall (element) via querySelector immediately changes the real physical structure, which is why builders (browsers) try to batch several wall changes together before recalculating the whole building's structural integrity (reflow) instead of doing it after every single nail.
Key Concepts
1
Selecting.
document.querySelector('.card') // the first match
document.querySelectorAll('.card') // all -- a static NodeList
document.getElementById('main') // fastest, by id2
querySelectorAll returns a static list — a snapshot. getElementsByClassName returns a live
collection that updates as the DOM changes, which surprises people iterating while removing.
querySelectorAllgetElementsByClassName
3
Creating and inserting.
const el = document.createElement('div');
el.textContent = 'Hello';
el.className = 'card';
parent.append(el);4
parent.append(a, b, 'text'); // several, and strings
el.before(x); el.after(y);
el.remove(); // no parent needed5
append and remove replaced appendChild and parentNode.removeChild, and are worth using.
appendremoveappendChildparentNode.removeChild
6
textContent against innerHTML.
el.textContent = userInput; // safe -- treated as text
el.innerHTML = userInput; // parses HTML -- XSStextContentinnerHTML
7
That is the security line. Any user-supplied string assigned to innerHTML can execute script. Use
textContent unless you are deliberately inserting markup you control.
innerHTMLtextContent
8
Attributes against properties.
el.setAttribute('data-id', '5');
el.dataset.id; // '5' -- the data-* API
el.value // the current value
el.getAttribute('value') // the ORIGINAL HTML attribute9
For form fields those two diverge as soon as the user types, which is a common source of "the value is
wrong".
10
Batch your changes. Each insertion into the live tree can trigger layout:
11
// 1000 reflows
items.forEach(i => list.append(makeItem(i)));12
// one
const frag = document.createDocumentFragment();
items.forEach(i => frag.append(makeItem(i)));
list.append(frag);13
And avoid layout thrashing — alternating reads and writes forces recalculation each time:
14
// bad: read, write, read, write
els.forEach(el => { el.style.height = el.offsetHeight + 10 + 'px'; });15
// good: read all, then write all
const hs = els.map(el => el.offsetHeight);
els.forEach((el, i) => el.style.height = hs[i] + 10 + 'px');16
What the interviewer is probing.1. "Why is innerHTML risky?" Probing: the injection risk. Stalls: "It is slower." *Moves
up:* it parses and executes markup, so untrusted content becomes XSS; textContent sets text safely.
17
2. "What is the difference between textContent and innerText?" Probing: the layout cost.
Stalls: "The same." Moves up: innerText respects styling and visibility so it forces a reflow to
compute; textContent reads the raw text and is faster.
18
3. "How do you add many elements efficiently?" Probing: batching. Stalls: "Append in a
loop." Moves up: build in a DocumentFragment or an HTML string and insert once, so the browser
lays out once rather than per element.
19
4. "querySelector or getElementById?" Probing: the trade. Stalls: "Always querySelector."
Moves up: getElementById is faster and clearer for an id; querySelector is worth it for anything
more complex.