DOM, BOM & Web APIs
JavaScript the language is tiny. JavaScript the platform â with the DOM, BOM, and hundreds of Web APIs â is vast. Senior engineers understand which APIs the browser provides, how the DOM tree maps to the render tree, and when to use native APIs instead of framework abstractions.
The DOM (Document Object Model)
The DOM is a tree-structured API that represents the HTML document as objects:
document
âââ html
âââ head
â âââ title
â âââ meta
âââ body
âââ header
â âââ nav
âââ main
â âââ h1
â âââ p
âââ footerDOM Selection Methods
// Modern â preferred
document.querySelector('.card'); // First match
document.querySelectorAll('.card'); // All matches (static NodeList)
element.closest('.parent'); // Nearest ancestor matching selector
// Legacy â still fast for simple lookups
document.getElementById('app'); // By ID (fastest)
document.getElementsByClassName('card'); // Live HTMLCollection
document.getElementsByTagName('div'); // Live HTMLCollectionKey distinction: querySelectorAll returns a static NodeList (snapshot). getElementsByClassName returns a live HTMLCollection (updates when DOM changes).
const live = document.getElementsByClassName('item');
const static_ = document.querySelectorAll('.item');
document.body.innerHTML += '<div class="item">New</div>';
live.length; // Updated â includes new element
static_.length; // Same as before â snapshotDOM Manipulation
const div = document.createElement('div');
div.className = 'card';
div.textContent = 'Hello';
div.setAttribute('data-id', '42');
parent.appendChild(div);
parent.insertBefore(div, referenceNode);
parent.removeChild(div);
parent.replaceChild(newNode, oldNode);
// Modern methods
parent.append(div, 'text', anotherDiv); // Append multiple nodes/strings
parent.prepend(div); // Insert at start
element.before(sibling); // Insert before element
element.after(sibling); // Insert after element
element.replaceWith(newElement); // Replace element
element.remove(); // Remove selfinnerHTML vs textContent vs innerText
| Property | Returns | XSS Risk | Performance |
|---|---|---|---|
innerHTML | HTML string | Yes â parses HTML | Slow (triggers parse) |
textContent | Raw text of all descendants | No | Fast |
innerText | Visible text (respects CSS) | No | Slow (triggers reflow) |
// DANGEROUS â XSS if userInput contains <script>
element.innerHTML = userInput;
// SAFE â escapes HTML
element.textContent = userInput;DocumentFragment for Batch DOM Updates
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
// Single DOM insertion â one reflow instead of 1000
list.appendChild(fragment);The BOM (Browser Object Model)
The BOM provides access to browser-level features outside the document:
window
window.innerWidth; // Viewport width (excluding scrollbar)
window.innerHeight; // Viewport height
window.outerWidth; // Browser window width
window.scrollX; // Horizontal scroll position
window.scrollY; // Vertical scroll position
window.devicePixelRatio; // Display density (1 = standard, 2 = retina)
window.open(url, '_blank');
window.close();
window.print();
window.scrollTo({ top: 0, behavior: 'smooth' });navigator
navigator.userAgent; // User agent string (unreliable for detection)
navigator.language; // Browser language ('en-US')
navigator.onLine; // Network connectivity
navigator.clipboard; // Clipboard API
navigator.geolocation; // Geolocation API
navigator.serviceWorker; // Service Worker registration
navigator.mediaDevices; // Camera/microphone access
navigator.share(data); // Web Share APIlocation
location.href; // Full URL
location.origin; // Protocol + host + port
location.pathname; // Path (/page/subpage)
location.search; // Query string (?key=value)
location.hash; // Fragment (#section)
location.hostname; // Domain name
location.assign(url); // Navigate (adds to history)
location.replace(url); // Navigate (replaces current entry)
location.reload(); // Reload pagehistory
history.pushState(state, '', '/new-url'); // Add entry without navigation
history.replaceState(state, '', '/url'); // Replace current entry
history.back(); // Go back
history.forward(); // Go forward
history.go(-2); // Go back 2 entries
window.addEventListener('popstate', (e) => {
console.log('Navigation:', e.state);
});pushState / replaceState is how SPAs implement client-side routing without full page reloads.
Essential Web APIs
Timers
const timeoutId = setTimeout(fn, delay); // Run once after delay
const intervalId = setInterval(fn, delay); // Run repeatedly
clearTimeout(timeoutId);
clearInterval(intervalId);
// requestAnimationFrame â syncs with display refresh
const rafId = requestAnimationFrame(callback);
cancelAnimationFrame(rafId);setTimeout(fn, 0) is not immediate â it schedules fn as a macrotask, running after the current call stack clears and all microtasks complete.
requestAnimationFrame
function animate(timestamp) {
element.style.transform = `translateX(${timestamp / 10}px)`;
if (timestamp < 2000) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);Runs at display refresh rate (~60fps). Pauses when tab is hidden. Always prefer over setInterval for visual animations.
Intersection Observer
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
loadImage(entry.target);
observer.unobserve(entry.target);
}
});
}, { rootMargin: '200px', threshold: 0 });
document.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));MutationObserver
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
if (mutation.type === 'childList') {
console.log('Children changed:', mutation.addedNodes, mutation.removedNodes);
}
});
});
observer.observe(element, { childList: true, subtree: true, attributes: true });ResizeObserver
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
console.log(`Resized to ${width}x${height}`);
}
});
observer.observe(element);Clipboard API
await navigator.clipboard.writeText('Copied text');
const text = await navigator.clipboard.readText();Geolocation API
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;
},
(error) => console.error(error.message),
{ enableHighAccuracy: true, timeout: 5000 }
);Interview Signal
Senior candidates demonstrate:
- DOM efficiency â DocumentFragment for batch inserts,
textContentoverinnerHTML, static vs live collections - BOM fluency â
history.pushStatefor SPA routing,navigatorAPI awareness - Modern APIs â IntersectionObserver over scroll events, ResizeObserver over window resize, MutationObserver for DOM watching
- Security awareness â
innerHTMLXSS risks,textContentas the safe alternative - Timer precision â
requestAnimationFramefor animation,setTimeout(fn, 0)as macrotask scheduling, timer clamping