This quiz is completed
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 buttonsubmit on a formmouseover on a divkeydown on an input6. 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 attachedevent.target refers to parent, event.currentTarget refers to childevent.currentTarget is only available on window8. How can you attach a click event to all list items efficiently?
Add a listener to each
li manuallyUse a loop with
setTimeout()Use event delegation on the
ul parentWrap 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 missingThe event listener is on the wrong element
submit events don't bubbleThe 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 laterforEach doesn't support NodeListsalert() can't be called from a loopquerySelectorAll attaches listeners globally13. 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 buttonthis is the parent div, not the clicked elemente.target should be used instead of thisBoth 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
thisEvents 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 worke is undefined inside the arrow functionclick events can't be delayedthis is incorrect inside the arrow function16. 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 usageonclick does not support functionsThe button has a higher z-index
The element with ID
btn doesn't exist at the time of assignment17. 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 elementUse
e.currentTarget instead of e.targetStop 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 targetsThe third argument
true enables bubblingThe 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 addEventListenerWrap 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 disabledThe button disables before the click action finishes
e.preventDefault() should be called21. 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 undefined23. Which is the best strategy for preventing
dblclick from interfering with click?Use
e.preventDefault() on both eventsTrack timestamps and ignore one
Use
setTimeout() with cancelation logic in clickBind
click only on single clicks using e.detail === 124. 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: nonepointerdown cancels the clickPointer 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 ittagName can be lowercase on some browsersButtons 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 constrequestAnimationFrame can run before scroll completesThe scroll handler re-enters before
ticking resetsThe
scroll event listener should be passive28. 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 elementsclick events are not allowed in shadow rootse.currentTarget should be used instead of e.target31. 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 handlerEvent 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 synchronously45. 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 asyncEvent listeners can only run once
e.target.value cannot be reassigned49. 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"));