xulhub.com
 What is event bubbling in the DOM?
The event flows from the root to the target element
The event flows from the target element to its ancestors
The event only affects the element that triggered it
The event duplicates itself at each level
2. What method stops an event from propagating up the DOM tree?
event.cancel()
event.preventDefault()
event.stopPropagation()
event.stopDefault()
3. Which method prevents the browser’s default behavior for an event?
event.preventDefault()
event.stopPropagation()
event.halt()
event.cancelBubble()
4. What is event delegation in JavaScript?
Assigning multiple listeners to child elements
Letting a parent handle events from its children
Passing events to external scripts
Preventing event bubbling completely
5. Which of the following events can be canceled using preventDefault()?
click on a button
submit on a form
mouseover on a div
keydown on an input
6. What is the purpose of event.target in an event listener?
The element that the event is attached to
The root of the DOM
The element where the event originated
The parent element that delegated the event
7. What’s the difference between event.target and event.currentTarget?
They are always the same
event.target is where the event started; event.currentTarget is where the handler is attached
event.target refers to parent, event.currentTarget refers to child
event.currentTarget is only available on window
8. How can you attach a click event to all list items efficiently?
Add a listener to each li manually
Use a loop with setTimeout()
Use event delegation on the ul parent
Wrap the list in a form element
9. Which option best describes the capturing phase?
The event flows from the target to the root
The event is canceled before reaching the target
The event flows from the root to the target
The event fires only on form submissions
10. What happens if both stopPropagation() and preventDefault() are called?
The event is cloned and canceled
The event continues to bubble but with no default behavior
The event does not bubble and the default action is prevented
The event is detached from the DOM tree
Given the code below, why does the form still submit?
document.querySelector("form").addEventListener("submit", (e) => {
  console.log("Form submitted");
});
e.preventDefault() is missing
The event listener is on the wrong element
submit events don't bubble
The form is invalid
12. What’s the issue in this setup for handling clicks on dynamic .item elements?
const items = document.querySelectorAll(".item");
items.forEach(item => {
  item.addEventListener("click", () => alert("Clicked"));
});
It won't work if .item elements are added later
forEach doesn't support NodeLists
alert() can't be called from a loop
querySelectorAll attaches listeners globally
13. Why might this not log the correct button that was clicked?
document.querySelector("div").addEventListener("click", function(e) {
  console.log(this.textContent);
});
this refers to the clicked button
this is the parent div, not the clicked element
e.target should be used instead of this
Both b and c
14. What causes a memory leak in the following scenario?
function setup() {
  const el = document.getElementById("demo");
  el.addEventListener("click", () => {
    console.log("clicked");
  });
}
// setup called many times
Listeners are not removed on repeated calls
The element ID is incorrect
Arrow function captures this
Events do not bubble from IDs
15. What's the bug in the following code when clicking a link?
document.querySelector("a").addEventListener("click", function(e) {
  setTimeout(() => {
    e.preventDefault();
  }, 100);
});
preventDefault() must be synchronous to work
e is undefined inside the arrow function
click events can't be delayed
this is incorrect inside the arrow function
16. Why does the following event not fire on the button?
document.getElementById("btn").onclick = handleClick;

function handleClick(e) {
  console.log("clicked");
}
handleClick is not defined before usage
onclick does not support functions
The button has a higher z-index
The element with ID btn doesn't exist at the time of assignment
17. Which fix would enable clicking on dynamically added .task elements?
document.querySelector("#list").addEventListener("click", (e) => {
  if (e.target.classList.contains("task")) {
    alert("Task clicked");
  }
});
This already uses proper delegation
Move the listener to each .task element
Use e.currentTarget instead of e.target
Stop event propagation before handling
18. In the code below, why might the log never appear?
document.body.addEventListener("click", function(e) {
  if (e.target.matches(".action")) {
    console.log("Action clicked");
  }
}, true);
matches doesn't work on event targets
The third argument true enables bubbling
The event listener is in capturing phase
Only anchor tags trigger the click event
19. Which option would best avoid multiple handlers on repeated renders?
function render() {
  const btn = document.getElementById("refresh");
  btn.addEventListener("click", () => console.log("Refreshed"));
}
Use .onclick instead of addEventListener
Wrap the listener in if (!btn.hasListener)
Remove the previous listener before adding
Declare the handler inline in HTML
20. What is the problem in this code for preventing double clicks?
const btn = document.querySelector("#submit");
btn.addEventListener("click", function(e) {
  e.target.disabled = true;
  submitForm();
});
The button re-enables itself too quickly
If submitForm throws, button remains disabled
The button disables before the click action finishes
e.preventDefault() should be called
21. In complex UIs, which scenario causes a "zombie listener" memory leak?
function attach() {
  const el = document.createElement("div");
  el.addEventListener("click", someHandler);
  document.body.appendChild(el);
}
// Element removed later without cleanup
The handler is declared as an arrow function
The element is removed using innerHTML = ''
The listener is bound inside a closure and never removed
The event is passive and doesn’t clean itself up
22. Which of these patterns creates subtle bugs in long-lived SPAs?
document.body.addEventListener("scroll", function() {
  // expensive computation
});
The event listener is too generic
Scroll events fire on document, not body
Scroll events are not throttled or debounced
this inside the function is undefined
23. Which is the best strategy for preventing dblclick from interfering with click?
Use e.preventDefault() on both events
Track timestamps and ignore one
Use setTimeout() with cancelation logic in click
Bind click only on single clicks using e.detail === 1
24. Why might the pointerdown event fire but not click?
element.addEventListener("pointerdown", handler);
element.addEventListener("click", () => console.log("clicked"));
The pointer is released outside the element
The element is display: none
pointerdown cancels the click
Pointer events never trigger clicks
25. Why does event.stopImmediatePropagation() exist?
To cancel default behavior more aggressively
To prevent other listeners on the same element from firing
To ensure event delegation fails
To block async event chains
26. What’s the core flaw in this delegation pattern?
container.addEventListener("click", (e) => {
  if (e.target.tagName === "BUTTON") {
    doSomething();
  }
});
Non-button elements inside <button> may trigger it
tagName can be lowercase on some browsers
Buttons may be shadow DOM elements
Events fired from SVG buttons won’t match
27. Why might this code fail to throttle the scroll event properly?
let ticking = false;
window.addEventListener("scroll", () => {
  if (!ticking) {
    requestAnimationFrame(() => {
      console.log("scrolling");
      ticking = false;
    });
    ticking = true;
  }
});
ticking is not declared as const
requestAnimationFrame can run before scroll completes
The scroll handler re-enters before ticking resets
The scroll event listener should be passive
28. In event delegation, why is e.stopPropagation() discouraged on the child element?
It prevents bubbling needed for delegation
It stops other children from receiving the event
It cancels e.preventDefault()
It disables the capturing phase
29. What is the impact of registering an event with { once: true }?
element.addEventListener("click", handler, { once: true });
The handler is removed after one invocation
The event fires twice, then is ignored
It blocks preventDefault()
The event skips bubbling
30. Which option best explains why this delegated event fails inside a shadow DOM?
document.body.addEventListener("click", (e) => {
  if (e.target.matches(".shadow-button")) {
    console.log("Clicked shadow button");
  }
});
Shadow DOM elements do not bubble to the main DOM by default
matches() doesn't work on shadow DOM elements
click events are not allowed in shadow roots
e.currentTarget should be used instead of e.target

31. Problem: A form submits even though you want to prevent submission. Which solution works?
<form id="myForm">...</form>

a)

document.getElementById("myForm").addEventListener("submit", => {
  e.preventDefault();
});

b)

document.getElementById("myForm").onsubmit = () => true;

c)

document.getElementById("myForm").addEventListener("click", => {
  e.preventDefault();
});

d)

document.getElementById("myForm").submit();
32. Problem: Dynamically added buttons don’t respond to clicks. Best fix? HTML:
<div id="container"></div>
<button class="btn">Button 1</button>


document.querySelectorAll(".btn").forEach(btn => {
  btn.addEventListener("click", () => alert("Clicked"));
});


document.getElementById("container").addEventListener("click", => {
  if(e.target.classList.contains("btn")) alert("Clicked");
});


document.querySelector("button").onclick = () => alert("Clicked");


document.addEventListener("click", () => alert("Clicked"));
33. Problem: event.preventDefault() isn’t stopping link navigation. What’s a correct fix?
<a href="https://example.com" id="link">Click me</a>

a)

document.getElementById("link").addEventListener("click", => {
  setTimeout(() => e.preventDefault(), 100);
});

b)

document.getElementById("link").addEventListener("click", => {
  e.preventDefault();
});

c)

document.getElementById("link").onclick = () => false;

d)

document.getElementById("link").addEventListener("click", () => {
  return false;
});
34. Problem: Too many event listeners slow down the app when adding many items. Best approach?

a)

items.forEach(item => item.addEventListener("click", handler));

b)

document.body.addEventListener("click", => {
  if (e.target.matches(".item")) handler(e);
});

c)

window.addEventListener("click", () => {});

d)

items.forEach(item => item.onclick = handler);
35. Problem: this inside event handler doesn’t refer to clicked button, how to fix?
button.addEventListener("click", () => {
  console.log(this.textContent);
});


button.addEventListener("click", function() {
  console.log(this.textContent);
});


button.addEventListener("click", () => {
  console.log(event.target.textContent);
});


button.addEventListener("click", => {
  console.log(e.currentTarget.textContent);
});


button.onclick = () => console.log(this.textContent);
36. Problem: A listener runs multiple times after re-render. How to fix?
function render() {
  const btn = document.getElementById("btn");
  btn.addEventListener("click", handler);
}


btn.removeEventListener("click", handler);
btn.addEventListener("click", handler);


btn.onclick = handler;


btn.addEventListener("click", handler, { once: true });


// No fix needed
37. Problem: Prevent scrolling while holding down space bar. Which is correct?


window.addEventListener("keydown", => {
  if (e.key === " " || e.code === "Space") e.preventDefault();
});


window.addEventListener("keypress", => {
  if (e.key === "Spacebar") e.preventDefault();
});


window.addEventListener("keyup", => {
  if (e.key === "Space") e.preventDefault();
});


window.addEventListener("keydown", => {
  if (e.code === "KeySpace") e.preventDefault();
});
38. Problem: Event delegation doesn't work for this child button inside a shadow DOM. What to do?


shadowRoot.addEventListener("click", handler);


document.body.addEventListener("click", handler);


shadowRoot.querySelector("button").addEventListener("click", handler);


document.addEventListener("shadowclick", handler);
39. Problem: A click event fires twice on a button, best fix?


button.addEventListener("click", handler);
button.addEventListener("dblclick", handler);


button.addEventListener("click", handler, { once: true });


button.removeEventListener("click", handler);


button.addEventListener("click", () => {
  setTimeout(handler, 200);
});
40. Problem: You want to stop click from bubbling but keep default browser behavior. Which code is correct?


element.addEventListener("click", => {
  e.stopPropagation();
});


element.addEventListener("click", => {
  e.preventDefault();
});


element.addEventListener("click", => {
  e.stopImmediatePropagation();
});


element.addEventListener("click", => {
  e.stopPropagation();
  e.preventDefault();
});

41. Why does this log "first" before "second"?
button.addEventListener("click", () => {
  console.log("first");
  Promise.resolve().then(() => console.log("second"));
});
Promises run synchronously
Microtasks run after the current call stack finishes
console.log inside Promise runs before event handler
Event listeners always run after promises
42. Which code ensures async handler completes before the next event fires?
button.addEventListener("click", async () => {
  await doSomething();
  console.log("done");
});


button.disabled = true;
await doSomething();
button.disabled = false;


doSomething().then(() => console.log("done"));


setTimeout(() => console.log("done"), 0);


button.addEventListener("click", () => console.log("done"));
43. Problem: Rapid clicks trigger multiple async handlers. Best debounce approach?


let timeout;
button.addEventListener("click", () => {
  clearTimeout(timeout);
  timeout = setTimeout(() => doAsyncStuff(), 300);
});


button.addEventListener("click", () => doAsyncStuff());

c)

button.addEventListener("click", () => {
  if (!button.disabled) doAsyncStuff();
});


button.addEventListener("click", async () => {
  await doAsyncStuff();
});
44. Why might event.preventDefault() inside a promise then() not work?
element.addEventListener("click", (e) => {
  Promise.resolve().then(() => e.preventDefault());
});
The event object is lost inside the promise
The default action happens before microtasks
Promises block the event loop
preventDefault() must be called synchronously
45. What happens if you call event.stopPropagation() inside an async callback?
It stops propagation immediately
It throws an error
It has no effect because propagation already happened
It delays propagation stopping until the callback finishes
46. What does this code print if button is clicked once?
button.addEventListener("click", () => {
  setTimeout(() => console.log("timeout"), 0);
  Promise.resolve().then(() => console.log("promise"));
  console.log("sync");
});
sync → promise → timeout
promise → timeout → sync
timeout → promise → sync
sync → timeout → promise
47. Problem: You want to block UI until an async validation finishes on input change. Which approach?


input.addEventListener("input", async => {
  const valid = await validate(e.target.value);
  if (!valid) alert("Invalid");
});


input.addEventListener("input", => {
  validate(e.target.value).then(valid => {
    if (!valid) alert("Invalid");
  });
});


input.addEventListener("input", => {
  while(!validateSync(e.target.value)) {}
});


input.addEventListener("input", => {
  setTimeout(() => validate(e.target.value), 0);
});
48. Why does this cause an infinite loop?
input.addEventListener("input", (e) => {
  e.target.value = e.target.value.toUpperCase();
});
Changing value triggers another input event
.toUpperCase() is async
Event listeners can only run once
e.target.value cannot be reassigned
49. Which is true about event listeners and async/await?
Async listeners pause event propagation
Async listeners delay next event handler until await completes
Async listeners return a promise ignored by the event system
Async listeners block UI rendering until resolved
50. What’s the correct way to wait for multiple async events before continuing?
button.addEventListener("click", () => {
  const p1 = fetch("/api/one");
  const p2 = fetch("/api/two");
});


Promise.all([p1, p2]).then(() => console.log("both done"));


p1.then(() => p2.then(() => console.log("both done")));


setTimeout(() => console.log("both done"), 0);


fetch("/api/one").then(() => fetch("/api/two")).then(() => console.log("both done"));