// Creating elements
const div = document.createElement('div');
div.id = 'container';
div.className = 'box rounded';
div.textContent = 'Hello World';
// Setting attributes
div.setAttribute('data-id', '123');
div.setAttribute('aria-label', 'Content container');
// Getting attributes
const id = div.getAttribute('data-id');
const hasAttr = div.hasAttribute('data-id');
// Removing attributes
div.removeAttribute('data-id');
// Appending to DOM
document.body.appendChild(div);
// Creating complex structures
const article = document.createElement('article');
const heading = document.createElement('h2');
heading.textContent = 'Article Title';
const paragraph = document.createElement('p');
paragraph.textContent = 'Article content...';
article.appendChild(heading);
article.appendChild(paragraph);
document.body.appendChild(article);
// Using DocumentFragment (efficient for multiple elements)
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i + 1}`;
fragment.appendChild(li);
}
// Single reflow instead of 100
document.getElementById('list').appendChild(fragment);
// innerHTML (use cautiously - XSS risk)
const container = document.getElementById('container');
container.innerHTML = '<h1>Title</h1><p>Content</p>';
// Safer: textContent
const text = document.getElementById('text');
text.textContent = 'Safe text content'; // No HTML parsed
// insertAdjacentHTML - insert at specific positions
const target = document.getElementById('target');
target.insertAdjacentHTML('beforebegin', '<div>Before target</div>');
target.insertAdjacentHTML('afterbegin', '<p>At start of target</p>');
target.insertAdjacentHTML('beforeend', '<p>At end of target</p>');
target.insertAdjacentHTML('afterend', '<div>After target</div>');
// classList manipulation
const element = document.getElementById('element');
element.classList.add('active', 'highlight');
element.classList.remove('inactive');
element.classList.toggle('visible');
if (element.classList.contains('active')) {
console.log('Element is active');
}
element.classList.replace('old-class', 'new-class');
// Style manipulation
element.style.color = 'red';
element.style.backgroundColor = 'blue';
element.style.fontSize = '16px';
// Multiple styles at once
Object.assign(element.style, {
color: 'red',
backgroundColor: 'blue',
fontSize: '16px',
padding: '1rem'
});
// Data attributes
const item = document.getElementById('item');
// Set data attributes
item.dataset.userId = '123';
item.dataset.userName = 'Alice';
item.dataset.itemType = 'product';
// Read data attributes
console.log(item.dataset.userId); // '123'
console.log(item.dataset.userName); // 'Alice'
// Equivalent to:
item.setAttribute('data-user-id', '123');
const userId = item.getAttribute('data-user-id');
// Removing elements
const oldElement = document.getElementById('old');
oldElement.remove(); // Modern way
// Or using parent
oldElement.parentNode.removeChild(oldElement);
// Replacing elements
const newElement = document.createElement('div');
newElement.textContent = 'New content';
oldElement.replaceWith(newElement);
// Cloning elements
const original = document.getElementById('template');
const clone = original.cloneNode(true); // true = deep clone
document.body.appendChild(clone);
// Querying DOM
const single = document.getElementById('unique-id');
const first = document.querySelector('.class-name');
const all = document.querySelectorAll('.items');
const byTag = document.getElementsByTagName('div');
const byClass = document.getElementsByClassName('box');
// Iterating NodeList
all.forEach(element => {
console.log(element.textContent);
});
// Converting to array
const array = Array.from(all);
const spread = [...all];
// Finding elements relative to another
const parent = element.parentElement;
const children = element.children;
const firstChild = element.firstElementChild;
const lastChild = element.lastElementChild;
const next = element.nextElementSibling;
const previous = element.previousElementSibling;
// Closest ancestor matching selector
const form = element.closest('form');
const container2 = element.closest('.container');
// Check if element matches selector
if (element.matches('.active')) {
console.log('Element has active class');
}
// Performance: Batch DOM changes
// Bad - causes multiple reflows
for (let i = 0; i < 100; i++) {
const div = document.createElement('div');
div.textContent = i;
document.body.appendChild(div); // Reflow each time
}
// Good - single reflow
const html = [];
for (let i = 0; i < 100; i++) {
html.push(`<div>${i}</div>`);
}
document.body.innerHTML += html.join('');
// Better - using fragment
const frag = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const div = document.createElement('div');
div.textContent = i;
frag.appendChild(div);
}
document.body.appendChild(frag);
// Read/write separation (prevent layout thrashing)
// Bad - interleaved reads and writes
const boxes = document.querySelectorAll('.box');
boxes.forEach(box => {
const height = box.offsetHeight; // Read (triggers layout)
box.style.height = height + 10 + 'px'; // Write
});
// Good - batch reads, then writes
const heights = [];
boxes.forEach(box => {
heights.push(box.offsetHeight);
});
boxes.forEach((box, i) => {
box.style.height = heights[i] + 10 + 'px';
});
// Virtual scrolling for large lists
class VirtualList {
constructor(container, items, itemHeight) {
this.container = container;
this.items = items;
this.itemHeight = itemHeight;
this.visibleCount = Math.ceil(container.offsetHeight / itemHeight);
this.render();
container.addEventListener('scroll', () => this.render());
}
render() {
const scrollTop = this.container.scrollTop;
const startIndex = Math.floor(scrollTop / this.itemHeight);
const endIndex = startIndex + this.visibleCount;
const visibleItems = this.items.slice(startIndex, endIndex);
this.container.innerHTML = '';
visibleItems.forEach((item, index) => {
const div = document.createElement('div');
div.textContent = item;
div.style.position = 'absolute';
div.style.top = (startIndex + index) * this.itemHeight + 'px';
div.style.height = this.itemHeight + 'px';
this.container.appendChild(div);
});
this.container.style.height = this.items.length * this.itemHeight + 'px';
}
}
// Sanitizing HTML (prevent XSS)
function sanitizeHTML(html) {
const div = document.createElement('div');
div.textContent = html; // Treats as text, not HTML
return div.innerHTML;
}
// Or use DOMPurify library for rich HTML
// const clean = DOMPurify.sanitize(dirtyHTML);
// Template element
const template = document.getElementById('item-template');
const clone2 = template.content.cloneNode(true);
// Modify clone
clone2.querySelector('.title').textContent = 'New Item';
clone2.querySelector('.description').textContent = 'Description';
document.getElementById('items').appendChild(clone2);
// Mutation Observer - watch DOM changes
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
console.log('Type:', mutation.type);
console.log('Target:', mutation.target);
});
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
characterData: true
});
// Stop observing
// observer.disconnect();
// Intersection Observer - visibility tracking
const intersectionObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('Element is visible');
entry.target.classList.add('visible');
}
});
});
document.querySelectorAll('.lazy-load').forEach(el => {
intersectionObserver.observe(el);
});