DOM (Document Object Model) is a document object model that represents HTML as a tree of objects:
// Basic DOM operations
document.getElementById('myId');
document.querySelector('.myClass');
element.innerHTML = 'New content';
element.addEventListener('click', handler);DOM is like a bridge between HTML markup and JavaScript! Browser transforms static HTML into a living tree of objects you can interact with. 🌉
DOM represents document as a tree:
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Hello</h1>
<p>Paragraph text</p>
</body>
</html>// Structure in DOM
document
├── html
├── head
│ └── title
│ └── "Title"
└── body
├── h1
│ └── "Hello"
└── p
└── "Paragraph text"// Main node types
Node.ELEMENT_NODE = 1; // <div>, <p>
Node.TEXT_NODE = 3; // Text content
Node.COMMENT_NODE = 8; // <!-- comment -->
Node.DOCUMENT_NODE = 9; // document
// Type checking
if (node.nodeType === Node.ELEMENT_NODE) {
console.log('This is an element');
}// By ID
const element = document.getElementById('myId');
// By class
const elements = document.getElementsByClassName('myClass');
// By tag
const paragraphs = document.getElementsByTagName('p');
// CSS selectors
const first = document.querySelector('.class');
const all = document.querySelectorAll('div > p');// Parent elements
element.parentNode;
element.parentElement;
// Child elements
element.childNodes; // All nodes
element.children; // Elements only
element.firstChild;
element.lastChild;
// Sibling elements
element.nextSibling;
element.previousSibling;
element.nextElementSibling;// Text content
element.textContent = 'New text';
element.innerText = 'Visible text';
// HTML content
element.innerHTML = '<strong>Bold text</strong>';
// Attributes
element.setAttribute('class', 'newClass');
element.getAttribute('id');
element.removeAttribute('style');// Direct style changes
element.style.color = 'red';
element.style.backgroundColor = 'blue';
element.style.fontSize = '16px';
// CSS classes
element.classList.add('active');
element.classList.remove('hidden');
element.classList.toggle('visible');
element.classList.contains('selected');// Creating new element
const div = document.createElement('div');
div.textContent = 'New block';
div.className = 'my-class';
// Adding to DOM
document.body.appendChild(div);
parent.insertBefore(div, referenceNode);
parent.insertAdjacentHTML('beforeend', '<p>HTML</p>');// Removing element
element.remove();
parent.removeChild(element);
// Replacing element
parent.replaceChild(newElement, oldElement);
// Cloning
const clone = element.cloneNode(true); // true = deep// Modern way
element.addEventListener('click', function(event) {
console.log('Click!', event.target);
});
// Multiple handlers
element.addEventListener('click', handler1);
element.addEventListener('click', handler2);
// Removing handler
element.removeEventListener('click', handler1);// Capture phase
element.addEventListener('click', handler, true);
// Stop propagation
function handler(event) {
event.stopPropagation();
event.preventDefault();
}
// Event delegation
document.addEventListener('click', function(event) {
if (event.target.matches('.button')) {
console.log('Button clicked');
}
});// Bad: multiple DOM access
for (let i = 0; i < 1000; i++) {
document.body.appendChild(createElement());
}
// Good: batch operations
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
fragment.appendChild(createElement());
}
document.body.appendChild(fragment);// Bad: repeated searches
document.getElementById('myId').style.color = 'red';
document.getElementById('myId').style.fontSize = '16px';
// Good: caching
const element = document.getElementById('myId');
element.style.color = 'red';
element.style.fontSize = '16px';// Tracking element visibility
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('Element is visible');
}
});
});
observer.observe(element);// Tracking DOM changes
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
console.log('DOM changed:', mutation.type);
});
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true
});// Slow operations
element.innerHTML = newContent; // Repaint
element.style.color = 'red'; // Reflow/Repaint// Virtual representation
const vdom = {
type: 'div',
props: { className: 'container' },
children: [
{ type: 'h1', children: 'Title' },
{ type: 'p', children: 'Text' }
]
};// Group changes
element.style.cssText = 'color: red; font-size: 16px;';
// Use classes instead of direct styles
element.className = 'active highlighted';// Instead of multiple handlers
document.addEventListener('click', function(event) {
const target = event.target;
if (target.matches('.button')) {
handleButton(target);
} else if (target.matches('.link')) {
handleLink(target);
}
});// Create elements on demand
function createExpensiveElement() {
if (!this.cachedElement) {
this.cachedElement = document.createElement('div');
// Setup element
}
return this.cachedElement;
}❌ Wrong:
// Searching in loop
for (let i = 0; i < items.length; i++) {
document.getElementById('list').appendChild(items[i]);
}
// Forgot about memory
element.addEventListener('click', handler);
// Didn't remove handler when removing element✅ Correct:
// Caching and batch operations
const list = document.getElementById('list');
const fragment = document.createDocumentFragment();
items.forEach(item => fragment.appendChild(item));
list.appendChild(fragment);
// Cleanup handlers
element.removeEventListener('click', handler);DOM is the foundation of web page interactivity:
Understanding DOM is key to effective web development! 🚀