0% found this document useful (0 votes)
40 views28 pages

DOM and BOM Interview Guide - JavaScript

DOM and BOM Interview Guide - JavaScript
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views28 pages

DOM and BOM Interview Guide - JavaScript

DOM and BOM Interview Guide - JavaScript
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 28

DOM and BOM Interview Guide - JavaScript

Table of Contents
1. DOM Fundamentals
2. DOM Selection Methods

3. DOM Manipulation
4. Event Handling

5. DOM Traversal
6. BOM (Browser Object Model)

7. Storage APIs

8. Advanced DOM Concepts

9. Performance Optimization

10. Common Interview Questions

DOM Fundamentals

What is DOM?
The Document Object Model (DOM) is a programming interface that represents HTML/XML documents
as a tree structure of objects that can be manipulated with JavaScript.

DOM Tree Structure

javascript
// DOM Tree Example
/*
Document
└── html
├── head
│ ├── title
│ └── meta
└── body
├── div (id="container")
│ ├── p (class="text")
│ └── span
└── script
*/

// Accessing the document


console.log(document); // The entire document
console.log(document.documentElement); // <html> element
console.log(document.head); // <head> element
console.log(document.body); // <body> element

Node Types

javascript

// Different node types


console.log(Node.ELEMENT_NODE); // 1
console.log(Node.TEXT_NODE); // 3
console.log(Node.COMMENT_NODE); // 8
console.log(Node.DOCUMENT_NODE); // 9

// Check node type


const element = document.getElementById('myDiv');
console.log(element.nodeType); // 1 (Element Node)
console.log(element.nodeName); // "DIV"
console.log(element.nodeValue); // null for elements

DOM Selection Methods

getElementById

javascript
// Select by ID (returns single element or null)
const element = document.getElementById('myId');
if (element) {
console.log('Element found:', element);
}

getElementsByClassName

javascript

// Select by class name (returns HTMLCollection)


const elements = document.getElementsByClassName('myClass');
console.log(elements.length); // Number of elements
console.log(elements[0]); // First element

// Convert to array for array methods


const elementsArray = Array.from(elements);
elementsArray.forEach(el => console.log(el));

getElementsByTagName

javascript

// Select by tag name (returns HTMLCollection)


const divs = document.getElementsByTagName('div');
const allElements = document.getElementsByTagName('*'); // All elements

querySelector (Modern Method)

javascript

// Select first matching element (returns element or null)


const element = document.querySelector('#myId'); // By ID
const element2 = document.querySelector('.myClass'); // By class
const element3 = document.querySelector('div.myClass'); // Tag + class
const element4 = document.querySelector('[data-id="123"]'); // By attribute

// Complex selectors
const complexSelect = document.querySelector('div > p:first-child');

querySelectorAll (Modern Method)

javascript
// Select all matching elements (returns NodeList)
const elements = document.querySelectorAll('.myClass');
const allDivs = document.querySelectorAll('div');

// NodeList has forEach method


elements.forEach((element, index) => {
console.log(`Element ${index}:`, element);
});

// Convert to array if needed


const elementsArray = [...elements];

Difference: HTMLCollection vs NodeList

javascript

// HTMLCollection (live) - updates automatically


const liveCollection = document.getElementsByClassName('test');

// NodeList (static) - snapshot at query time


const staticList = document.querySelectorAll('.test');

// Add new element with class 'test'


document.body.innerHTML += '<div class="test">New</div>';

console.log(liveCollection.length); // Updated count


console.log(staticList.length); // Original count

DOM Manipulation

Creating Elements

javascript
// Create new elements
const div = document.createElement('div');
const textNode = document.createTextNode('Hello World');
const fragment = document.createDocumentFragment();

// Set attributes and content


div.id = 'newDiv';
div.className = 'container';
div.textContent = 'New content';
div.innerHTML = '<span>HTML content</span>';

// Using setAttribute
div.setAttribute('data-id', '123');
div.setAttribute('aria-label', 'Container');

Adding Elements to DOM

javascript

// Append methods
const parent = document.getElementById('container');
const child = document.createElement('p');
child.textContent = 'New paragraph';

// Different append methods


parent.appendChild(child); // Adds to end
parent.insertBefore(child, parent.firstChild); // Insert before first child
parent.insertAdjacentElement('afterbegin', child); // Insert at beginning
parent.insertAdjacentElement('beforeend', child); // Insert at end

// Modern methods
parent.append(child); // Can append multiple nodes/strings
parent.prepend(child); // Add to beginning
parent.before(child); // Insert before parent
parent.after(child); // Insert after parent

Modifying Content

javascript
const element = document.getElementById('myDiv');

// Text content (safe from XSS)


element.textContent = 'Plain text content';

// HTML content (can execute scripts - be careful!)


element.innerHTML = '<strong>Bold text</strong>';

// Outer HTML (replaces entire element)


element.outerHTML = '<div id="replaced">New element</div>';

// Insert adjacent HTML


element.insertAdjacentHTML('beforebegin', '<p>Before element</p>');
element.insertAdjacentHTML('afterbegin', '<span>At start</span>');
element.insertAdjacentHTML('beforeend', '<span>At end</span>');
element.insertAdjacentHTML('afterend', '<p>After element</p>');

Modifying Attributes

javascript

const element = document.getElementById('myDiv');

// Get attributes
const id = element.getAttribute('id');
const className = element.getAttribute('class');

// Set attributes
element.setAttribute('data-value', '100');
element.setAttribute('title', 'Tooltip text');

// Remove attributes
element.removeAttribute('title');

// Check if attribute exists


if (element.hasAttribute('data-value')) {
console.log('Data value exists');
}

// Dataset API for data attributes


element.dataset.userId = '123'; // Creates data-user-id="123"
element.dataset.itemCount = '5'; // Creates data-item-count="5"
console.log(element.dataset.userId); // "123"

Modifying Styles
javascript

const element = document.getElementById('myDiv');

// Inline styles
element.style.color = 'red';
element.style.backgroundColor = 'blue';
element.style.fontSize = '16px';

// CSS properties with hyphens become camelCase


element.style.borderRadius = '5px';
element.style.marginTop = '10px';

// Get computed styles


const computedStyle = window.getComputedStyle(element);
console.log(computedStyle.color);
console.log(computedStyle.fontSize);

// CSS classes
element.className = 'new-class'; // Replace all classes
element.classList.add('class1', 'class2'); // Add classes
element.classList.remove('class1'); // Remove class
element.classList.toggle('active'); // Toggle class
element.classList.contains('active'); // Check if class exists
element.classList.replace('old-class', 'new-class'); // Replace class

Removing Elements

javascript
const element = document.getElementById('myDiv');

// Modern method
element.remove(); // Removes element from DOM

// Legacy method
element.parentNode.removeChild(element);

// Remove all children


const parent = document.getElementById('container');
parent.innerHTML = ''; // Simple but not recommended for large amounts

// Better approach for removing children


while (parent.firstChild) {
parent.removeChild(parent.firstChild);
}

// Or using replaceChildren (modern)


parent.replaceChildren(); // Removes all children

Event Handling

Adding Event Listeners

javascript
// addEventListener (recommended)
const button = document.getElementById('myButton');

function handleClick(event) {
console.log('Button clicked!');
console.log('Event type:', event.type);
console.log('Target:', event.target);
console.log('Current target:', event.currentTarget);
}

button.addEventListener('click', handleClick);

// With options
button.addEventListener('click', handleClick, {
once: true, // Execute only once
passive: true, // Never calls preventDefault
capture: true // Capture phase
});

// Arrow function
button.addEventListener('click', (e) => {
console.log('Arrow function handler');
});

// Multiple event types


['mouseenter', 'mouseleave'].forEach(eventType => {
button.addEventListener(eventType, handleMouseEvent);
});

Event Object Properties

javascript
function handleEvent(event) {
// Prevent default behavior
event.preventDefault();

// Stop event bubbling


event.stopPropagation();

// Stop all event handlers


event.stopImmediatePropagation();

// Event properties
console.log('Type:', event.type);
console.log('Target:', event.target); // Element that triggered event
console.log('Current Target:', event.currentTarget); // Element with listener
console.log('Timestamp:', event.timeStamp);

// Mouse events
if (event.type.startsWith('mouse')) {
console.log('Client X:', event.clientX);
console.log('Client Y:', event.clientY);
console.log('Page X:', event.pageX);
console.log('Page Y:', event.pageY);
console.log('Button:', event.button); // 0=left, 1=middle, 2=right
}

// Keyboard events
if (event.type.startsWith('key')) {
console.log('Key:', event.key);
console.log('Code:', event.code);
console.log('Ctrl:', event.ctrlKey);
console.log('Shift:', event.shiftKey);
console.log('Alt:', event.altKey);
}
}

Event Bubbling and Capturing

javascript
// HTML structure: div > button
const div = document.getElementById('container');
const button = document.getElementById('myButton');

// Bubbling phase (default)


div.addEventListener('click', () => console.log('Div clicked (bubbling)'));
button.addEventListener('click', () => console.log('Button clicked (bubbling)'));

// Capturing phase
div.addEventListener('click', () => console.log('Div clicked (capturing)'), true);
button.addEventListener('click', () => console.log('Button clicked (capturing)'), true);

// Order: Div capturing -> Button capturing -> Button bubbling -> Div bubbling

Event Delegation

javascript

// Instead of adding listeners to each item


const container = document.getElementById('itemContainer');

container.addEventListener('click', function(event) {
// Check if clicked element matches selector
if (event.target.matches('.item-button')) {
console.log('Item button clicked:', event.target.textContent);
}

// Or check by class
if (event.target.classList.contains('delete-btn')) {
const item = event.target.closest('.item');
item.remove();
}
});

// Benefits: Works for dynamically added elements, better performance

Custom Events

javascript
// Create custom event
const customEvent = new CustomEvent('myCustomEvent', {
detail: { message: 'Hello from custom event!' },
bubbles: true,
cancelable: true
});

// Listen for custom event


document.addEventListener('myCustomEvent', function(event) {
console.log('Custom event received:', event.detail.message);
});

// Dispatch custom event


document.dispatchEvent(customEvent);

// Alternative syntax
const simpleEvent = new Event('simpleEvent');
document.dispatchEvent(simpleEvent);

Removing Event Listeners

javascript

const button = document.getElementById('myButton');

function clickHandler() {
console.log('Clicked!');
}

// Add listener
button.addEventListener('click', clickHandler);

// Remove listener (must be same function reference)


button.removeEventListener('click', clickHandler);

// Using AbortController (modern approach)


const controller = new AbortController();

button.addEventListener('click', clickHandler, {
signal: controller.signal
});

// Remove all listeners added with this controller


controller.abort();
DOM Traversal

Parent Relationships

javascript

const element = document.getElementById('child');

// Parent relationships
console.log(element.parentNode); // Direct parent (any node type)
console.log(element.parentElement); // Parent element (null if parent is not element)
console.log(element.closest('.container')); // Closest ancestor matching selector

// Check if element contains another


const parent = document.getElementById('parent');
const child = document.getElementById('child');
console.log(parent.contains(child)); // true/false

Child Relationships

javascript

const parent = document.getElementById('parent');

// All children (including text nodes)


console.log(parent.childNodes); // NodeList with all child nodes
console.log(parent.firstChild); // First child node
console.log(parent.lastChild); // Last child node

// Element children only


console.log(parent.children); // HTMLCollection with element children only
console.log(parent.firstElementChild); // First element child
console.log(parent.lastElementChild); // Last element child
console.log(parent.childElementCount); // Number of element children

// Check if has children


console.log(parent.hasChildNodes()); // Any child nodes
console.log(parent.children.length > 0); // Element children

Sibling Relationships

javascript
const element = document.getElementById('middle');

// All siblings (including text nodes)


console.log(element.previousSibling); // Previous sibling node
console.log(element.nextSibling); // Next sibling node

// Element siblings only


console.log(element.previousElementSibling); // Previous element sibling
console.log(element.nextElementSibling); // Next element sibling

// Get all siblings


function getAllSiblings(element) {
const siblings = [];
let sibling = element.parentElement.firstElementChild;

while (sibling) {
if (sibling !== element) {
siblings.push(sibling);
}
sibling = sibling.nextElementSibling;
}

return siblings;
}

Advanced Traversal Methods

javascript
// TreeWalker for complex traversal
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_ELEMENT,
{
acceptNode: function(node) {
return node.classList.contains('highlight')
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_SKIP;
}
}
);

let node;
while (node = walker.nextNode()) {
console.log(node);
}

// NodeIterator
const iterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_TEXT
);

let textNode;
while (textNode = iterator.nextNode()) {
console.log(textNode.textContent.trim());
}

BOM (Browser Object Model)

Window Object

javascript
// Window properties
console.log(window.innerWidth); // Viewport width
console.log(window.innerHeight); // Viewport height
console.log(window.outerWidth); // Browser window width
console.log(window.outerHeight); // Browser window height
console.log(window.screenX); // Window position X
console.log(window.screenY); // Window position Y

// Window methods
window.alert('Alert message');
window.confirm('Confirm this action?');
const userInput = window.prompt('Enter your name:');

// Open/close windows
const newWindow = window.open('https://example.com', '_blank', 'width=800,height=600');
newWindow.close();

// Scroll methods
window.scrollTo(0, 100); // Scroll to position
window.scrollBy(0, 50); // Scroll by amount
document.getElementById('element').scrollIntoView(); // Scroll element into view

Location Object

javascript

// Current URL information


console.log(location.href); // Full URL
console.log(location.protocol); // http: or https:
console.log(location.host); // domain.com:port
console.log(location.hostname); // domain.com
console.log(location.port); // port number
console.log(location.pathname); // /path/to/page
console.log(location.search); // ?query=string
console.log(location.hash); // #fragment

// Navigation methods
location.assign('https://example.com'); // Navigate to URL
location.replace('https://example.com'); // Replace current page in history
location.reload(); // Reload page
location.reload(true); // Force reload from server

// Modify URL without reload


location.hash = '#newSection'; // Changes fragment
// location.search = '?newQuery=value'; // Would reload page
History Object

javascript

// History navigation
history.back(); // Go back one page
history.forward(); // Go forward one page
history.go(-2); // Go back 2 pages
history.go(1); // Go forward 1 page

// History length
console.log(history.length); // Number of entries in history

// Modern History API


history.pushState({page: 1}, 'Title', '/new-url'); // Add new history entry
history.replaceState({page: 2}, 'New Title', '/updated-url'); // Replace current entry

// Listen for history changes


window.addEventListener('popstate', function(event) {
console.log('History state:', event.state);
console.log('Current URL:', location.pathname);
});

Navigator Object

javascript
// Browser information
console.log(navigator.userAgent); // Browser user agent string
console.log(navigator.platform); // Operating system
console.log(navigator.language); // Preferred language
console.log(navigator.languages); // Array of languages
console.log(navigator.cookieEnabled); // Cookies enabled
console.log(navigator.onLine); // Online status

// Geolocation API
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
console.log('Latitude:', position.coords.latitude);
console.log('Longitude:', position.coords.longitude);
},
function(error) {
console.log('Geolocation error:', error.message);
}
);
}

// Clipboard API
if (navigator.clipboard) {
navigator.clipboard.writeText('Text to copy').then(() => {
console.log('Text copied to clipboard');
});

navigator.clipboard.readText().then(text => {
console.log('Clipboard content:', text);
});
}

Screen Object

javascript

// Screen information
console.log(screen.width); // Screen width
console.log(screen.height); // Screen height
console.log(screen.availWidth); // Available screen width
console.log(screen.availHeight); // Available screen height
console.log(screen.colorDepth); // Color depth
console.log(screen.pixelDepth); // Pixel depth
console.log(screen.orientation.angle); // Screen orientation angle
Timers

javascript

// setTimeout - execute once after delay


const timeoutId = setTimeout(() => {
console.log('Executed after 2 seconds');
}, 2000);

// Cancel timeout
clearTimeout(timeoutId);

// setInterval - execute repeatedly


const intervalId = setInterval(() => {
console.log('Executed every second');
}, 1000);

// Cancel interval
clearInterval(intervalId);

// requestAnimationFrame - for smooth animations


function animate() {
// Animation code here
console.log('Animation frame');
requestAnimationFrame(animate);
}
const animationId = requestAnimationFrame(animate);

// Cancel animation
cancelAnimationFrame(animationId);

Storage APIs

localStorage

javascript
// Store data (persists until manually cleared)
localStorage.setItem('username', 'john_doe');
localStorage.setItem('preferences', JSON.stringify({theme: 'dark', lang: 'en'}));

// Retrieve data
const username = localStorage.getItem('username');
const preferences = JSON.parse(localStorage.getItem('preferences') || '{}');

// Remove item
localStorage.removeItem('username');

// Clear all
localStorage.clear();

// Get all keys


for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
console.log(key, localStorage.getItem(key));
}

// Storage event (fires when storage changes in another tab)


window.addEventListener('storage', function(event) {
console.log('Storage changed:', event.key, event.oldValue, event.newValue);
});

sessionStorage

javascript

// Store data (persists until tab is closed)


sessionStorage.setItem('tempData', 'temporary value');

// Same API as localStorage


const tempData = sessionStorage.getItem('tempData');
sessionStorage.removeItem('tempData');
sessionStorage.clear();

Cookies (Legacy)

javascript
// Set cookie
document.cookie = "username=john_doe; expires=Thu, 18 Dec 2024 12:00:00 UTC; path=/";

// Get all cookies


console.log(document.cookie);

// Helper functions for cookies


function setCookie(name, value, days) {
const expires = new Date();
expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));
document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`;
}

function getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
}

function deleteCookie(name) {
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
}

Advanced DOM Concepts

MutationObserver

javascript
// Observe DOM changes
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log('Mutation type:', mutation.type);

if (mutation.type === 'childList') {


console.log('Added nodes:', mutation.addedNodes);
console.log('Removed nodes:', mutation.removedNodes);
}

if (mutation.type === 'attributes') {


console.log('Attribute changed:', mutation.attributeName);
console.log('Old value:', mutation.oldValue);
}
});
});

// Start observing
const targetNode = document.getElementById('observeMe');
observer.observe(targetNode, {
childList: true, // Observe child additions/removals
attributes: true, // Observe attribute changes
attributeOldValue: true, // Include old attribute values
subtree: true, // Observe descendants too
characterData: true // Observe text content changes
});

// Stop observing
observer.disconnect();

Intersection Observer

javascript
// Observe element visibility
const intersectionObserver = new IntersectionObserver(function(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('Element is visible:', entry.target);
// Lazy load images, trigger animations, etc.
} else {
console.log('Element is not visible:', entry.target);
}
});
}, {
threshold: 0.5, // Trigger when 50% visible
rootMargin: '10px' // Margin around the root
});

// Start observing elements


const elementsToObserve = document.querySelectorAll('.lazy-load');
elementsToObserve.forEach(el => intersectionObserver.observe(el));

ResizeObserver

javascript

// Observe element size changes


const resizeObserver = new ResizeObserver(function(entries) {
entries.forEach(entry => {
console.log('Element resized:', entry.target);
console.log('New size:', entry.contentRect.width, 'x', entry.contentRect.height);

// Respond to size changes


if (entry.contentRect.width < 300) {
entry.target.classList.add('small');
} else {
entry.target.classList.remove('small');
}
});
});

// Observe element
const resizableElement = document.getElementById('resizable');
resizeObserver.observe(resizableElement);

Shadow DOM

javascript
// Create shadow DOM
const hostElement = document.getElementById('shadow-host');
const shadowRoot = hostElement.attachShadow({mode: 'open'}); // or 'closed'

// Add content to shadow DOM


shadowRoot.innerHTML = `
<style>
p { color: red; }
</style>
<p>This is in the shadow DOM</p>
`;

// Access shadow DOM


console.log(hostElement.shadowRoot); // Available if mode is 'open'

// Custom Elements with Shadow DOM


class MyCustomElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({mode: 'open'});

shadow.innerHTML = `
<style>
:host {
display: block;
padding: 10px;
border: 1px solid #ccc;
}
</style>
<slot></slot>
`;
}
}

customElements.define('my-custom-element', MyCustomElement);

Performance Optimization

Document Fragments

javascript
// Efficient way to add multiple elements
const fragment = document.createDocumentFragment();

// Add multiple elements to fragment (no reflow/repaint)


for (let i = 0; i < 1000; i++) {
const div = document.createElement('div');
div.textContent = `Item ${i}`;
fragment.appendChild(div);
}

// Single DOM update (only one reflow/repaint)


document.getElementById('container').appendChild(fragment);

Batch DOM Updates

javascript

const container = document.getElementById('container');

// Bad: Multiple DOM updates


for (let i = 0; i < 100; i++) {
const div = document.createElement('div');
div.textContent = `Item ${i}`;
container.appendChild(div); // DOM update each iteration
}

// Good: Single DOM update


const html = [];
for (let i = 0; i < 100; i++) {
html.push(`<div>Item ${i}</div>`);
}
container.innerHTML = html.join('');

// Best: Using DocumentFragment


const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const div = document.createElement('div');
div.textContent = `Item ${i}`;
fragment.appendChild(div);
}
container.appendChild(fragment);

Debouncing and Throttling

javascript
// Debounce function
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}

// Throttle function
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}

// Usage examples
const searchInput = document.getElementById('search');
const debouncedSearch = debounce(function(event) {
console.log('Searching for:', event.target.value);
}, 300);

searchInput.addEventListener('input', debouncedSearch);

const throttledScroll = throttle(function() {


console.log('Scroll position:', window.scrollY);
}, 100);

window.addEventListener('scroll', throttledScroll);

Virtual Scrolling Concept

javascript
// Basic virtual scrolling implementation
class VirtualList {
constructor(container, items, itemHeight) {
this.container = container;
this.items = items;
this.itemHeight = itemHeight;
this.visibleCount = Math.ceil(container.clientHeight / itemHeight);
this.scrollTop = 0;

this.render();
this.bindEvents();
}

render() {
const startIndex = Math.floor(this.scrollTop / this.itemHeight);
const endIndex = Math.min(startIndex + this.visibleCount, this.items.length);

let html = '';


for (let i = startIndex; i < endIndex; i++) {
html += `<div style="height: ${this.itemHeight}px">${this.items[i]}</div>`;
}

this.container.innerHTML = html;
this.container.style.paddingTop = `${startIndex * this.itemHeight}px`;
this.container.style.paddingBottom = `${(this.items.length - endIndex) * this.itemHeight}px`;
}

bindEvents() {
this.container.addEventListener('scroll', () => {
this.scrollTop = this.container.scrollTop;
this.render();
});
}
}

// Usage
const items = Array.from({length: 10000}, (_, i) => `Item ${i}`);
const virtualList = new VirtualList(document.getElementById('list'), items, 30);

Common Interview Questions

1. What's the difference between innerHTML, textContent, and innerText?

javascript
const element = document.createElement('div');
element.innerHTML = '<span>Hello <strong>World</strong></span>';

console.log(element.innerHTML); // "<span>Hello <strong>World</strong></span>"


console.log(element.textContent); // "Hello World"
console.log(element.innerText); // "Hello World" (considers styling)

// Key differences:
// - innerHTML: Gets/sets HTML content (can execute scripts)
// - textContent: Gets/sets text content (ignores styling, includes hidden text)
// - innerText: Gets/sets text content (considers styling, excludes hidden text)

2. Event Bubbling vs Capturing

javascript

// Bubbling: Event travels from target to root


// Capturing: Event travels from root to target

document.getElementById('parent').addEventListener('click', () => {
console.log('Parent clicked (bubbling)');
}, false); // false = bubbling phase

document.getElementById('child').addEventListener('click', () => {
console.log('Child clicked (bubbling)');
}, false);

// Order when child is clicked: Child -> Parent

document.getElementById('parent').addEventListener('click', () => {
console.log('Parent clicked (capturing)');
}, true); // true = capturing phase

// Order with capturing: Parent (capturing) -> Child -> Parent (bubbling)

3. How to prevent memory leaks with event listeners?

javascript

// Problem: Event

You might also like