DOM & Events

10 questions found

What is event bubbling?

Beginner
Event bubbling means an event fired on an element propagates upward through its ancestors in the DOM tree, triggering any matching event listeners on parents after the target element's own listeners run.
document.getElementById('parent').addEventListener('click', () => console.log('parent clicked'));
document.getElementById('child').addEventListener('click', () => console.log('child clicked'));
// clicking child logs 'child clicked' then 'parent clicked'
Real-world example A single click listener on a <ul> catching clicks from any <li> inside it, instead of attaching a listener to every item.

Common follow-ups: How do you stop an event from bubbling further?

Design Patterns in JavaScript

What does event.preventDefault() do?

Beginner
It cancels the browser's default action for that event — like following a link's href, submitting a form, or checking a checkbox — while still allowing the event to bubble unless you also stop propagation.
form.addEventListener('submit', (e) => {
  e.preventDefault();
  validateAndSubmitViaFetch();
});
Real-world example Intercepting a form submission to send data via fetch() instead of a full page reload.

Common follow-ups: Does preventDefault() also stop event bubbling? (No — that's stopPropagation().)

Networking: Fetch XHR WebSockets & CORS

How do you select and modify an element's text content?

Beginner
Use document.querySelector() (or similar) to find the element, then set its textContent property to update the text safely without interpreting it as HTML.
const el = document.querySelector('#status');
el.textContent = 'Saved successfully';
Real-world example Updating a status message on screen after a save action completes.

Common follow-ups: What's the security risk of using innerHTML instead of textContent with user input?

Security: XSS CSRF & Content Security Policy

What is event delegation and why is it a performance best practice?

Intermediate
Event delegation attaches a single listener to a common ancestor and uses event.target to determine which child triggered it, instead of attaching a separate listener to every child — this uses far less memory and automatically works for dynamically added children.
document.getElementById('list').addEventListener('click', (e) => {
  if (e.target.matches('li')) {
    console.log('Clicked item:', e.target.textContent);
  }
});
Real-world example Handling clicks on rows of a dynamically loaded, potentially thousands-of-items-long table.

Common follow-ups: What DOM property tells you which element actually triggered the event versus which listener caught it?

Performance Optimization: Debouncing Throttling & Memoization

What's the difference between event.target and event.currentTarget?

Intermediate
event.target is the actual element that originated the event (e.g., the specific <li> clicked); event.currentTarget is the element the listener is currently attached to and executing on (e.g., the parent <ul> during bubbling).
list.addEventListener('click', (e) => {
  console.log(e.target);        // the <li> clicked
  console.log(e.currentTarget); // the <ul> the listener is on
});
Real-world example Using target to identify which specific button in a toolbar was clicked, while currentTarget stays constant.

Common follow-ups: Does currentTarget change value during the bubbling phase?

Design Patterns in JavaScript

How do you create and dispatch a custom DOM event?

Intermediate
Construct a CustomEvent with an optional detail payload, then call dispatchEvent() on a target element; other code can listen for it exactly like a native event.
const event = new CustomEvent('itemAdded', { detail: { id: 42 } });
el.addEventListener('itemAdded', (e) => console.log(e.detail.id));
el.dispatchEvent(event); // logs 42
Real-world example Decoupling a cart component from a header badge by having them communicate via a custom 'cartUpdated' event.

Common follow-ups: Does a custom event bubble by default?

Design Patterns in JavaScript

What's the difference between the capturing and bubbling phases of event propagation?

Advanced
Events actually travel in three phases: capturing (top-down, from window to the target), target phase, then bubbling (bottom-up, target back to window). Listeners default to the bubbling phase; pass { capture: true } to react during the capturing phase instead.
el.addEventListener('click', handler, { capture: true }); // fires during capture (top-down)
el.addEventListener('click', handler); // fires during bubble (bottom-up), the default
Real-world example Intercepting a click at a top-level container BEFORE it reaches a deeply nested element that might call stopPropagation().

Common follow-ups: Can you stop propagation during the capturing phase to prevent a click reaching its target at all?

Design Patterns in JavaScript

How do you properly clean up event listeners to avoid memory leaks?

Advanced
Call removeEventListener() with the exact same function reference and options used in addEventListener() — anonymous inline functions can't be removed this way, so store a named reference if you'll need to detach it later.
function handleClick() { console.log('clicked'); }
el.addEventListener('click', handleClick);
// later:
el.removeEventListener('click', handleClick);
Real-world example Removing listeners in a React useEffect cleanup function or when a component/widget is destroyed.

Common follow-ups: Why do arrow functions defined inline in addEventListener() cause a common removeEventListener bug?

Memory Management & Garbage Collection

What is the difference between passive and non-passive event listeners for scroll performance?

Advanced
A passive listener ({ passive: true }) tells the browser up front that it will never call preventDefault(), letting the browser start scrolling immediately without waiting for the handler to finish — significantly improving scroll smoothness for touch/wheel events.
el.addEventListener('touchstart', handleTouch, { passive: true });
Real-world example Fixing janky scrolling on mobile caused by a touchstart/touchmove listener that doesn't actually need to block scrolling.

Common follow-ups: What happens if a passive listener DOES call preventDefault() anyway?

Performance Optimization: Debouncing Throttling & Memoization

How does MutationObserver let you react to DOM changes made by other code?

Advanced
MutationObserver watches a target node (and optionally its subtree) for changes like added/removed children, attribute changes, or text changes, and asynchronously batches callbacks — useful for reacting to DOM mutations from third-party scripts you don't control.
const observer = new MutationObserver((mutations) => {
  mutations.forEach(m => console.log(m.type, m.target));
});
observer.observe(document.body, { childList: true, subtree: true });
Real-world example Detecting when a third-party widget injects new DOM nodes so your code can style or enhance them.

Common follow-ups: How does MutationObserver differ from the older, deprecated Mutation Events?

Design Patterns in JavaScript