π¨ JavaScript Β· Topic 17 of 20
Events β JavaScript Questions with Answers
30 practice questions on Events, each with the correct answer and a clear explanation of why it is right. Read through them as revision notes, or take this topic as an interactive quiz to test yourself.
1 easy Β· 17 medium Β· 12 hard Β· Part of JavaScript: The language of the web - basics to advanced, 20 topics.
Medium questions (17)
Q3. medium
What is the event object passed to a handler?
btn.addEventListener("click", (e) => {
console.log(e.type, e.target, e.clientX);
});
- A An object describing what happened - target, type, coordinates, key pressed, etc.
- B The element only
- C A string
- D Nothing is passed
Answer: A β An object describing what happened - target, type, coordinates, key pressed, etc.
Every handler receives the event as its first argument (conventionally e or event), carrying details and control methods like preventDefault.
Event object
Q5. medium
What does e.preventDefault() do?
form.addEventListener("submit", (e) => {
e.preventDefault(); // stop page reload
sendData();
});
- A Stops the browser's default action - e.g. a form submitting or a link navigating
- B Stops the event bubbling
- C Removes the listener
- D Prevents all events
Answer: A β Stops the browser's default action - e.g. a form submitting or a link navigating
Essential for handling forms with JavaScript, since without it the page reloads and your code appears to do nothing.
preventDefaultForms
Q6. medium
What does e.stopPropagation() do?
- A Prevents the event from continuing to bubble up to ancestor elements
- B Stops the default action
- C Deletes the event
- D Cancels all listeners on the page
Answer: A β Prevents the event from continuing to bubble up to ancestor elements
Useful when an inner element's click should not also trigger a parent's handler (e.g. clicking inside a modal should not close it). Use sparingly - it can make behaviour hard to trace.
stopPropagationBubbling
Q10. medium
Why does event delegation work for elements added dynamically?
- A The listener is on the parent, which already exists - new children bubble to it automatically
- B The browser re-scans listeners
- C It does not work for new elements
- D JavaScript adds listeners automatically
Answer: A β The listener is on the parent, which already exists - new children bubble to it automatically
Directly attached listeners only cover elements present at the time. Delegation solves the common bug where newly created buttons stop responding.
DelegationDynamic content
Q11. medium
How do you REMOVE an event listener?
function onClick() { }
btn.addEventListener("click", onClick);
btn.removeEventListener("click", onClick); // works
- A removeEventListener with the SAME function reference used to add it
- B removeEventListener("click")
- C el.listeners = []
- D delete el.onclick
Answer: A β removeEventListener with the SAME function reference used to add it
An anonymous inline arrow cannot be removed because you have no reference to it. Store the function in a variable if you plan to remove it.
removeEventListenerCleanup
Q12. medium
What does the { once: true } option do?
btn.addEventListener("click", init, { once: true });
- A The listener fires at most once, then removes itself automatically
- B It fires once per second
- C It only works on one element
- D Nothing
Answer: A β The listener fires at most once, then removes itself automatically
Ideal for one-time actions like an intro animation or a single-submit guard - no manual cleanup needed.
Listener options
Q13. medium
Which event fires as the user TYPES in an input?
search.addEventListener("input", (e) => filter(e.target.value));
- A input - it fires on every change, including paste
- B change - only when leaving the field
- C keypress only
- D submit
Answer: A β input - it fires on every change, including paste
Use input for live search or character counters. change fires only after the value is committed (blur or selection), which is better for selects and checkboxes.
inputchange
Q14. medium
How do you detect which key was pressed?
input.addEventListener("keydown", (e) => {
if (e.key === "Enter") submit();
});
- A e.key - a readable string like "Enter", "a", "ArrowUp"
- B e.keyCode only
- C e.char
- D e.button
Answer: A β e.key - a readable string like "Enter", "a", "ArrowUp"
e.key is the modern, readable property. e.keyCode is deprecated. Use e.code when you need the physical key regardless of layout.
Keyboard eventse.key
Q15. medium
What is the difference between keydown and keyup?
- A keydown fires when the key goes DOWN (and repeats if held); keyup fires on release
- B They are identical
- C keyup fires first
- D keydown only works for letters
Answer: A β keydown fires when the key goes DOWN (and repeats if held); keyup fires on release
Use keydown for shortcuts and to preventDefault before the character appears; use keyup when you need the final state after the key is released.
Keyboard events
Q17. medium
What is the difference between mouseover and mouseenter?
- A mouseover BUBBLES and re-fires when moving over children; mouseenter fires once for the element itself
- B They are identical
- C mouseenter bubbles
- D mouseover works only on links
Answer: A β mouseover BUBBLES and re-fires when moving over children; mouseenter fires once for the element itself
mouseenter/mouseleave are usually what you want for hover effects, because mouseover fires repeatedly as the pointer crosses child elements.
Mouse events
Q19. medium
Which event should you use to run code after the page's HTML is ready?
- A DOMContentLoaded
- B click
- C resize
- D beforeunload
Answer: A β DOMContentLoaded
DOMContentLoaded fires as soon as the DOM is parsed. Alternatively, adding defer to your script tag achieves the same effect without a listener.
DOMContentLoadedPage lifecycle
Q21. medium
What does the { passive: true } listener option indicate?
window.addEventListener("touchstart", fn, { passive: true });
- A That the handler will NOT call preventDefault, letting the browser scroll without waiting
- B That the listener runs once
- C That the event is ignored
- D That it captures
Answer: A β That the handler will NOT call preventDefault, letting the browser scroll without waiting
Passive touch/wheel listeners improve scrolling smoothness because the browser need not block to see whether you cancel the default.
PerformanceTouch events
Q23. medium
What is this inside a REGULAR function event handler?
- A The element the listener is attached to (same as e.currentTarget)
- B window
- C The event object
- D undefined
Answer: A β The element the listener is attached to (same as e.currentTarget)
The DOM binds this to the current element - but an ARROW handler inherits this from the outer scope instead, so use e.currentTarget there.
thisEvents
Q24. medium
Can one element have TWO listeners for the same event?
- A Yes with addEventListener - they run in the order added
- B No, only one
- C Only with capture
- D Only on different elements
Answer: A β Yes with addEventListener - they run in the order added
This is a key advantage over the onclick property, which each new assignment overwrites.
addEventListenerMultiple handlers
Q26. medium
Which event fires when a form is submitted?
- A submit (on the FORM element)
- B click on the button only
- C send
- D post
Answer: A β submit (on the FORM element)
Listen on the form, not the button - that way Enter-key submission is also captured. Then call e.preventDefault() to handle it in JavaScript.
Formssubmit
Q28. medium
What does the change event on a checkbox give you?
cb.addEventListener("change", e => console.log(e.target.checked));
- A It fires when checked state changes - read e.target.checked (a boolean)
- B It gives the text value
- C It fires on hover
- D It does not work on checkboxes
Answer: A β It fires when checked state changes - read e.target.checked (a boolean)
For checkboxes and radios use .checked, not .value (which is the static value attribute).
FormsCheckboxes
Q30. medium
Which is better for a list of 100 buttons: 100 listeners or 1 delegated listener?
- A One delegated listener on the parent - less memory and it covers future items
- B 100 individual listeners
- C They are identical
- D Neither works
Answer: A β One delegated listener on the parent - less memory and it covers future items
Delegation is the standard solution for lists, tables and any dynamically generated content.
DelegationPerformance
Hard questions (12)
Q2. hard
What is wrong here?
btn.addEventListener("click", handleClick());
btn.addEventListener("click", handleClick); // correct
btn.addEventListener("click", () => handleClick(5)); // with args
- A The parentheses CALL handleClick immediately and register its return value instead of the function
- B Nothing is wrong
- C The event name is wrong
- D It needs three arguments
Answer: A β The parentheses CALL handleClick immediately and register its return value instead of the function
Pass the function itself (no parentheses). If you must pass arguments, wrap it: () => handleClick(id).
- A top beginner mistake with event listeners.
CallbacksCommon mistakes
Q4. hard
What is the difference between e.target and e.currentTarget?
- A target is the element that ACTUALLY triggered the event; currentTarget is the element the listener is attached to
- B They are always the same
- C currentTarget is the parent
- D target is always the document
Answer: A β target is the element that ACTUALLY triggered the event; currentTarget is the element the listener is attached to
Clicking a <span> inside a button makes target the span but currentTarget the button. This distinction is the key to event delegation.
targetcurrentTargetDelegation
Q7. hard
What is event BUBBLING?
- A An event fires on the target, then travels UP through each ancestor, triggering their handlers
- B Events go downward from document
- C Events repeat
- D Events fire twice
Answer: A β An event fires on the target, then travels UP through each ancestor, triggering their handlers
Click a button inside a div inside body: handlers fire on the button, then the div, then body, then document. Bubbling is what makes delegation possible.
BubblingPropagation
Q8. hard
What are the three phases of event propagation?
el.addEventListener("click", fn, true); // capture phase
- A Capturing (down), target, then bubbling (up)
- B Start, middle, end
- C Click, hold, release
- D Only bubbling exists
Answer: A β Capturing (down), target, then bubbling (up)
The event descends from document to the target (capture), fires at the target, then bubbles back up. Passing true (or {capture: true}) to addEventListener runs your handler during the capture phase.
CapturingBubbling
Q9. hard
What is event DELEGATION?
list.addEventListener("click", (e) => {
const btn = e.target.closest(".delete");
if (!btn) return;
btn.closest("li").remove();
});
- A Attaching ONE listener to a parent and using e.target to handle events from many children
- B Assigning events to another developer
- C Using multiple listeners per element
- D Removing listeners
Answer: A β Attaching ONE listener to a parent and using e.target to handle events from many children
Instead of a listener per row, put one on the container. It uses less memory and automatically covers elements added LATER - the standard pattern for dynamic lists.
DelegationPerformance
Q16. hard
How do you read all values from a form on submit?
form.addEventListener("submit", (e) => {
e.preventDefault();
const data = Object.fromEntries(new FormData(form));
console.log(data.email);
});
- A const data = Object.fromEntries(new FormData(form))
- B form.values
- C form.data()
- D JSON.parse(form)
Answer: A β const data = Object.fromEntries(new FormData(form))
FormData collects every named field; fromEntries turns it into a plain object. Remember to call e.preventDefault() first.
FormDataForms
Q18. hard
What is the output order?
parent.addEventListener("click", () => console.log("parent"));
child.addEventListener("click", () => console.log("child"));
// user clicks child
- A child then parent - the event bubbles upward
- B parent then child
- C Only child
- D Only parent
Answer: A β child then parent - the event bubbles upward
Default listeners run in the bubbling phase, starting at the target. Adding {capture: true} to the parent would make it fire FIRST instead.
BubblingOrder
Q20. hard
Why should scroll and resize handlers be throttled or debounced?
- A They fire extremely often, so heavy work in them causes janky, slow scrolling
- B They are disabled by default
- C They only fire once
- D No reason
Answer: A β They fire extremely often, so heavy work in them causes janky, slow scrolling
Scroll can fire dozens of times per second. Throttle limits the rate; debounce waits for a pause. For visibility detection, IntersectionObserver is better still.
PerformanceDebounceThrottle
Q22. hard
How do you trigger a custom event?
el.addEventListener("cart:add", e => console.log(e.detail.id));
el.dispatchEvent(new CustomEvent("cart:add", { detail: { id: 7 } }));
- A el.dispatchEvent(new CustomEvent("myEvent", { detail: data }))
- B el.trigger("myEvent")
- C el.fire("myEvent")
- D Custom events are impossible
Answer: A β el.dispatchEvent(new CustomEvent("myEvent", { detail: data }))
CustomEvent lets components communicate without direct coupling. The listener reads the payload from e.detail.
CustomEventComponent communication
Q25. hard
What does e.stopImmediatePropagation() add over stopPropagation()?
- A It also prevents OTHER listeners on the SAME element from running
- B Nothing extra
- C It removes the listener
- D It prevents the default action
Answer: A β It also prevents OTHER listeners on the SAME element from running
stopPropagation only halts the journey to ancestors; remaining handlers on the same element still fire. stopImmediatePropagation stops those too.
Propagation control
Q27. hard
Why might a listener attached in a loop capture the wrong value?
for (var i = 0; i < 3; i++) btns[i].addEventListener("click", () => console.log(i));
- A var creates ONE shared binding, so every handler logs 3 - use let
- B Listeners cannot be added in loops
- C btns is undefined
- D It works correctly
Answer: A β var creates ONE shared binding, so every handler logs 3 - use let
The same closure trap as with setTimeout. Changing var to let gives each iteration its own binding, so the handlers log 0, 1 and 2.
Closureslet vs var
Q29. hard
Why remove event listeners when destroying a component?
const ac = new AbortController();
window.addEventListener("resize", fn, { signal: ac.signal });
ac.abort(); // removes it
- A Listeners keep references alive, preventing garbage collection - a memory leak
- B It is purely cosmetic
- C Listeners expire automatically
- D To reset the page
Answer: A β Listeners keep references alive, preventing garbage collection - a memory leak
Especially for listeners on window/document that reference removed elements. React's useEffect cleanup and AbortController exist for exactly this.
Memory leaksAbortController