Problem Statement
Explain different ways to manipulate the DOM. Compare innerHTML, textContent, createElement, and when to use each.
Explanation
JavaScript provides multiple methods for DOM manipulation, each with different use cases, performance, and security implications.
InnerHTML:
Gets or sets HTML content as a string. Parses HTML and creates elements. Fast for large replacements. Security risk with user input due to XSS attacks. Use for trusted HTML content or templates. Avoid for user-generated content.
TextContent:
Gets or sets text content without HTML parsing. Faster and safer than innerHTML. Includes hidden text. Use for plain text to prevent XSS. Best for user input display. No security concerns.
InnerText:
Gets visible text respecting CSS display. Triggers reflow, slower than textContent. Excludes hidden elements. Use when you need only visible text. Less common in practice.
CreateElement with appendChild:
Creates elements programmatically. Most secure and flexible. Better performance for single elements. Full control over attributes and properties. Use for dynamic element creation. Best for complex structures.
InsertAdjacentHTML:
Inserts HTML at specific position. Does not replace existing content. More efficient than innerHTML for additions. Same XSS risk as innerHTML. Use for adding content without replacing.
Document Fragment:
Creates off-screen container for multiple elements. Add many elements, then append once. Minimizes reflows and repaints. Best performance for bulk operations. Use when adding many elements.
When to use each:
Use textContent for user-generated text. Use createElement for programmatic element creation. Use innerHTML only for trusted HTML templates. Use document fragments for multiple elements. Always sanitize user input.
Performance considerations:
TextContent is fastest for text. InnerHTML is fast for bulk replacements. CreateElement is best for single elements. Document fragments optimize multiple additions.
Security best practices:
Never use innerHTML with user input. Always escape or sanitize user data. Prefer textContent or createElement. Use Content Security Policy. Validate on server side too.
Code Solution
SolutionRead Only
// innerHTML - HTML parsing
const container = document.getElementById('container');
// Set HTML content
container.innerHTML = '<p>Hello <strong>World</strong></p>';
// Creates actual <p> and <strong> elements
// Get HTML content
console.log(container.innerHTML);
// '<p>Hello <strong>World</strong></p>'
// SECURITY RISK with user input
const userInput = '<img src=x onerror="alert(\'XSS\')">';
// container.innerHTML = userInput; // DANGER! Executes script
// Safe alternative for user input
container.textContent = userInput; // Displays as text
// textContent - Plain text
// Set text (safe)
container.textContent = 'Plain text <b>not parsed</b>';
// Displays: Plain text <b>not parsed</b>
// Get all text (includes hidden)
const div = document.createElement('div');
div.innerHTML = 'Visible <span style="display:none">Hidden</span>';
console.log(div.textContent); // 'Visible Hidden'
console.log(div.innerText); // 'Visible' (excludes hidden)
// createElement - Programmatic creation
function createCard(title, description) {
const card = document.createElement('div');
card.className = 'card';
const heading = document.createElement('h3');
heading.textContent = title; // Safe
const para = document.createElement('p');
para.textContent = description; // Safe
const button = document.createElement('button');
button.textContent = 'Click';
button.addEventListener('click', () => {
console.log('Clicked:', title);
});
card.appendChild(heading);
card.appendChild(para);
card.appendChild(button);
return card;
}
container.appendChild(createCard('Title', 'Description'));
// PERFORMANCE COMPARISON
// Slow - multiple reflows
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
list.appendChild(li); // Reflow each time!
}
// Fast - one reflow with fragment
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
list.appendChild(fragment); // One reflow!
// Fast - innerHTML for bulk
const html = Array.from({length: 100}, (_, i) =>
`<li>Item ${i}</li>`
).join('');
list.innerHTML = html;
// insertAdjacentHTML - Positioned insertion
const element = document.getElementById('target');
// Four positions:
element.insertAdjacentHTML('beforebegin', '<p>Before</p>');
element.insertAdjacentHTML('afterbegin', '<p>First child</p>');
element.insertAdjacentHTML('beforeend', '<p>Last child</p>');
element.insertAdjacentHTML('afterend', '<p>After</p>');
// REAL-WORLD EXAMPLES
// Example 1: Render user list (safe)
function renderUsers(users) {
const list = document.getElementById('userList');
list.innerHTML = ''; // Clear
users.forEach(user => {
const li = document.createElement('li');
li.className = 'user-item';
const name = document.createElement('span');
name.textContent = user.name; // Safe from XSS
const email = document.createElement('span');
email.textContent = user.email;
li.appendChild(name);
li.appendChild(email);
list.appendChild(li);
});
}
// Example 2: Template with safe interpolation
function createProductCard(product) {
const template = document.createElement('div');
template.className = 'product';
// Safe way to build HTML
const img = document.createElement('img');
img.src = product.image;
img.alt = product.name;
const title = document.createElement('h3');
title.textContent = product.name;
const price = document.createElement('p');
price.textContent = `$${product.price}`;
template.append(img, title, price);
return template;
}
// Example 3: Efficient list rendering
function renderLargeList(items) {
const fragment = document.createDocumentFragment();
items.forEach(item => {
const div = document.createElement('div');
div.textContent = item;
fragment.appendChild(div);
});
container.appendChild(fragment);
}
// WHEN TO USE WHAT
// Use textContent:
// - User input display
// - Plain text updates
// - Security-sensitive content
// Use innerHTML:
// - Trusted HTML templates
// - Bulk HTML generation
// - Performance-critical bulk updates
// Use createElement:
// - Single element creation
// - Complex element structures
// - When you need event listeners
// - Maximum security and control
// Use document fragment:
// - Adding multiple elements
// - Performance-critical operations
// - Reducing reflows