[{"data":1,"prerenderedAt":2814},["ShallowReactive",2],{"page-\u002Fjs\u002F20-events":3},{"id":4,"title":5,"body":6,"description":217,"extension":2808,"meta":2809,"navigation":47,"path":2810,"seo":2811,"stem":2812,"__hash__":2813},"content\u002Fjs\u002F20-events.md","20 — Events",{"type":7,"value":8,"toc":2771},"minimark",[9,13,114,194,440,536,622,738,972,1073,1225,1299,1506,1592,1732,1994,2091,2193,2357,2479,2547,2767],[10,11,5],"h1",{"id":12},"_20-events",[14,15,16,34,86],"question-wrapper",{},[17,18,20,21,25,26,29,30,33],"h3",{"id":19},"q1-in-the-default-event-flow-model-used-by-the-dom-what-happens-when-a-user-clicks-a-deeply-nested-span-inside-several-wrapping-div-elements-assuming-no-listener-calls-stoppropagation","Q1. In the default event flow model used by the DOM, what happens when a user clicks a deeply nested ",[22,23,24],"code",{},"\u003Cspan>"," inside several wrapping ",[22,27,28],{},"\u003Cdiv>"," elements, assuming no listener calls ",[22,31,32],{},"stopPropagation()","?",[35,36,39,56,65,77],"ul",{"className":37},[38],"contains-task-list",[40,41,44,49,50,52,53],"li",{"className":42},[43],"task-list-item",[45,46],"input",{"disabled":47,"type":48},true,"checkbox"," The click event fires on the ",[22,51,24],{}," first, then propagates upward, firing on each ancestor in turn up to ",[22,54,55],{},"document",[40,57,59,61,62,64],{"className":58},[43],[45,60],{"disabled":47,"type":48}," The click event fires only on the ",[22,63,24],{},"; ancestor elements never see it",[40,66,68,70,71,73,74,76],{"className":67},[43],[45,69],{"disabled":47,"type":48}," The click event fires on ",[22,72,55],{}," first, then downward to the ",[22,75,24],{},", then stops",[40,78,80,82,83,85],{"className":79},[43],[45,81],{"disabled":47,"type":48}," The click event fires on every ancestor and the ",[22,84,24],{}," at the same time, in an unspecified order",[87,88,89,93,105],"details",{},[90,91,92],"summary",{},"Show Answer",[94,95,96,100,101,52,103],"p",{},[97,98,99],"strong",{},"Answer:"," A — The click event fires on the ",[22,102,24],{},[22,104,55],{},[94,106,107,110,111,113],{},[97,108,109],{},"Explanation:"," This is the bubbling phase, the default direction of event flow: the event originates at the deepest element the user interacted with (the \"target phase\"), then walks up the ancestor chain, firing any matching listener on each ancestor in turn, unless something calls ",[22,112,32],{},". Option B ignores bubbling entirely. Option C describes only the capturing phase (which does run top-down, but before the target phase, not instead of bubbling) and incorrectly claims it \"stops.\" Option D is wrong because the phases are strictly sequential and deterministic, never simultaneous.",[14,115,116,124,162],{},[17,117,119,120,123],{"id":118},"q2-by-default-elementaddeventlistenerclick-handler-registers-the-handler-for-which-phase-of-the-event-flow","Q2. By default, ",[22,121,122],{},"element.addEventListener('click', handler)"," registers the handler for which phase of the event flow?",[35,125,127,133,139,149],{"className":126},[38],[40,128,130,132],{"className":129},[43],[45,131],{"disabled":47,"type":48}," The capturing phase, so it runs before any bubbling-phase listeners on ancestors",[40,134,136,138],{"className":135},[43],[45,137],{"disabled":47,"type":48}," The bubbling phase, so it runs after the capturing phase has already passed through this element",[40,140,142,144,145,148],{"className":141},[43],[45,143],{"disabled":47,"type":48}," Both phases simultaneously, unless ",[22,146,147],{},"capture: false"," is explicitly set",[40,150,152,154,155,158,159],{"className":151},[43],[45,153],{"disabled":47,"type":48}," Neither phase — plain calls without ",[22,156,157],{},"{capture: true}"," only fire when the element is the exact ",[22,160,161],{},"event.target",[87,163,164,166,171],{},[90,165,92],{},[94,167,168,170],{},[97,169,99],{}," B — The bubbling phase, so it runs after the capturing phase has already passed through this element",[94,172,173,175,176,179,180,183,184,187,188,190,191,193],{},[97,174,109],{}," ",[22,177,178],{},"addEventListener","'s third argument defaults to ",[22,181,182],{},"false"," (or an options object with ",[22,185,186],{},"capture"," omitted, which also defaults to ",[22,189,182],{},"), meaning the handler is registered for the bubbling phase. The full dispatch always runs capturing (root → target) first, regardless of what any individual listener requests, before bubbling-phase listeners get their turn. Option A describes what ",[22,192,157],{}," does. Option C is nonsensical — a listener is bound to one phase's behavior. Option D is too restrictive: a bubbling-phase listener on an ancestor fires too, once the event bubbles up to it, not only when it's the exact target.",[14,195,197,209,373,376,403],{"language":196},"javascript",[17,198,200,201,204,205,208],{"id":199},"q3-given-nested-elements-where-inner-is-a-direct-child-of-outer-and-the-following-listeners","Q3. Given nested elements where ",[22,202,203],{},"inner"," is a direct child of ",[22,206,207],{},"outer",", and the following listeners:",[210,211,212],"code-wrapper",{"language":196},[213,214,218],"pre",{"className":215,"code":216,"language":196,"meta":217,"style":217},"language-javascript shiki shiki-themes github-light github-dark","outer.addEventListener(\"click\", () => console.log(\"outer bubble\"));\nouter.addEventListener(\"click\", () => console.log(\"outer capture\"), { capture: true });\n\ninner.addEventListener(\"click\", () => console.log(\"inner capture\"), { capture: true });\ninner.addEventListener(\"click\", () => console.log(\"inner bubble\"));\n\ninner.click();\n","",[22,219,220,260,294,300,331,357,362],{"__ignoreMap":217},[221,222,225,229,232,235,239,242,246,249,252,254,257],"span",{"class":223,"line":224},"line",1,[221,226,228],{"class":227},"ssxIu","outer.",[221,230,178],{"class":231},"sIsaT",[221,233,234],{"class":227},"(",[221,236,238],{"class":237},"sJ6F3","\"click\"",[221,240,241],{"class":227},", () ",[221,243,245],{"class":244},"svdQ7","=>",[221,247,248],{"class":227}," console.",[221,250,251],{"class":231},"log",[221,253,234],{"class":227},[221,255,256],{"class":237},"\"outer bubble\"",[221,258,259],{"class":227},"));\n",[221,261,263,265,267,269,271,273,275,277,279,281,284,287,291],{"class":223,"line":262},2,[221,264,228],{"class":227},[221,266,178],{"class":231},[221,268,234],{"class":227},[221,270,238],{"class":237},[221,272,241],{"class":227},[221,274,245],{"class":244},[221,276,248],{"class":227},[221,278,251],{"class":231},[221,280,234],{"class":227},[221,282,283],{"class":237},"\"outer capture\"",[221,285,286],{"class":227},"), { capture: ",[221,288,290],{"class":289},"snvgF","true",[221,292,293],{"class":227}," });\n",[221,295,297],{"class":223,"line":296},3,[221,298,299],{"emptyLinePlaceholder":47},"\n",[221,301,303,306,308,310,312,314,316,318,320,322,325,327,329],{"class":223,"line":302},4,[221,304,305],{"class":227},"inner.",[221,307,178],{"class":231},[221,309,234],{"class":227},[221,311,238],{"class":237},[221,313,241],{"class":227},[221,315,245],{"class":244},[221,317,248],{"class":227},[221,319,251],{"class":231},[221,321,234],{"class":227},[221,323,324],{"class":237},"\"inner capture\"",[221,326,286],{"class":227},[221,328,290],{"class":289},[221,330,293],{"class":227},[221,332,334,336,338,340,342,344,346,348,350,352,355],{"class":223,"line":333},5,[221,335,305],{"class":227},[221,337,178],{"class":231},[221,339,234],{"class":227},[221,341,238],{"class":237},[221,343,241],{"class":227},[221,345,245],{"class":244},[221,347,248],{"class":227},[221,349,251],{"class":231},[221,351,234],{"class":227},[221,353,354],{"class":237},"\"inner bubble\"",[221,356,259],{"class":227},[221,358,360],{"class":223,"line":359},6,[221,361,299],{"emptyLinePlaceholder":47},[221,363,365,367,370],{"class":223,"line":364},7,[221,366,305],{"class":227},[221,368,369],{"class":231},"click",[221,371,372],{"class":227},"();\n",[94,374,375],{},"What is the console output order?",[35,377,379,385,391,397],{"className":378},[38],[40,380,382,384],{"className":381},[43],[45,383],{"disabled":47,"type":48}," inner bubble, inner capture, outer bubble, outer capture",[40,386,388,390],{"className":387},[43],[45,389],{"disabled":47,"type":48}," outer bubble, outer capture, inner capture, inner bubble",[40,392,394,396],{"className":393},[43],[45,395],{"disabled":47,"type":48}," outer capture, inner capture, inner bubble, outer bubble",[40,398,400,402],{"className":399},[43],[45,401],{"disabled":47,"type":48}," inner capture, outer capture, outer bubble, inner bubble",[87,404,405,407,412],{},[90,406,92],{},[94,408,409,411],{},[97,410,99],{}," C — outer capture, inner capture, inner bubble, outer bubble",[94,413,414,175,416,419,420,422,423,425,426,428,429,431,432,436,437,439],{},[97,415,109],{},[97,417,418],{},"Debug."," The capturing phase travels from the root down to (but not including firing bubble listeners at) the target, so ",[22,421,207],{},"'s capture-flagged listener fires first as the event descends toward ",[22,424,203],{},". Once the event reaches the target element itself, the dispatch is in the \"at target\" phase — here, both of ",[22,427,203],{},"'s listeners fire regardless of their ",[22,430,186],{}," flag, in the order they were ",[433,434,435],"em",{},"registered",", which is why \"inner capture\" logs before \"inner bubble\" (it was added first in this snippet, not because capture flags dictate ordering at the target). Finally the bubbling phase carries the event back up, firing ",[22,438,207],{},"'s bubble-phase listener last. The key gotcha: at the target element, registration order — not the capture flag — decides the sequence.",[14,441,442,464,507],{},[17,443,445,446,449,450,452,453,455,456,459,460,463],{"id":444},"q4-a-button-has-two-separate-click-listeners-attached-via-addeventlistener-the-first-one-calls-eventstoppropagation-the-second-one-does-nothing-special-both-are-registered-directly-on-the-button-no-capture-option-no-stopimmediatepropagation-when-the-button-is-clicked-what-happens-to-the-second-listener","Q4. A ",[22,447,448],{},"\u003Cbutton>"," has two separate ",[22,451,369],{}," listeners attached via ",[22,454,178],{},". The first one calls ",[22,457,458],{},"event.stopPropagation()","; the second one does nothing special. Both are registered directly on the button (no capture option, no ",[22,461,462],{},"stopImmediatePropagation","). When the button is clicked, what happens to the second listener?",[35,465,467,476,485,494],{"className":466},[38],[40,468,470,472,473,475],{"className":469},[43],[45,471],{"disabled":47,"type":48}," It never runs — ",[22,474,32],{}," also stops other listeners on the same element",[40,477,479,481,482,484],{"className":478},[43],[45,480],{"disabled":47,"type":48}," Neither listener runs — ",[22,483,32],{}," cancels the event entirely",[40,486,488,490,491,493],{"className":487},[43],[45,489],{"disabled":47,"type":48}," Only the second listener runs — ",[22,492,32],{}," blocks the listener that called it from completing",[40,495,497,499,500,502,503,506],{"className":496},[43],[45,498],{"disabled":47,"type":48}," It still runs — ",[22,501,32],{}," only stops bubbling to ancestor listeners, not sibling listeners on the same element; ",[22,504,505],{},"stopImmediatePropagation()"," would be needed to block it too",[87,508,509,511,520],{},[90,510,92],{},[94,512,513,515,516,502,518,506],{},[97,514,99],{}," D — It still runs — ",[22,517,32],{},[22,519,505],{},[94,521,522,175,524,175,526,528,529,532,533,535],{},[97,523,109],{},[97,525,418],{},[22,527,32],{}," only prevents the event from continuing to travel to ancestor (or, during capturing, descendant) elements — it has no effect on other listeners already queued on the ",[433,530,531],{},"same"," element, which all still run in registration order. Only ",[22,534,505],{}," additionally halts remaining same-element listeners. Option A is the classic mix-up between the two methods. Option B overstates the effect — propagation control never cancels the event object itself. Option C inverts which listener is affected.",[14,537,538,553,589],{},[17,539,541,542,545,546,548,549,552],{"id":540},"q5-calling-eventpreventdefault-inside-a-click-handler-on-an-a-hrefpage-link-does-which-of-the-following","Q5. Calling ",[22,543,544],{},"event.preventDefault()"," inside a ",[22,547,369],{}," handler on an ",[22,550,551],{},"\u003Ca href=\"\u002Fpage\">"," link does which of the following?",[35,554,556,569,577,583],{"className":555},[38],[40,557,559,561,562,565,566,568],{"className":558},[43],[45,560],{"disabled":47,"type":48}," Prevents the browser's default navigation to ",[22,563,564],{},"\u002Fpage",", but the event still bubbles to ancestor listeners unless ",[22,567,32],{}," is also called",[40,570,572,561,574,576],{"className":571},[43],[45,573],{"disabled":47,"type":48},[22,575,564],{},", and also stops the event from bubbling to ancestor listeners",[40,578,580,582],{"className":579},[43],[45,581],{"disabled":47,"type":48}," Has no effect unless the listener is registered on the capturing phase",[40,584,586,588],{"className":585},[43],[45,587],{"disabled":47,"type":48}," Cancels the entire event, so no other listener on the anchor element runs",[87,590,591,593,602],{},[90,592,92],{},[94,594,595,597,598,565,600,568],{},[97,596,99],{}," A — Prevents the browser's default navigation to ",[22,599,564],{},[22,601,32],{},[94,603,604,175,606,609,610,612,613,615,616,618,619,621],{},[97,605,109],{},[22,607,608],{},"preventDefault()"," and propagation control are two independent mechanisms: ",[22,611,608],{}," only suppresses whatever built-in action the browser would otherwise take (navigating, submitting a form, toggling a checkbox), while propagation continues normally unless ",[22,614,32],{},"\u002F",[22,617,505],{}," is called separately. Option B conflates the two, a very common assumption. Option C is wrong — ",[22,620,608],{}," works from either phase. Option D is wrong — it has no effect on other listeners at all.",[14,623,624,638,704],{},[17,625,627,628,631,632,635,636,33],{"id":626},"q6-a-ul-contains-500-li-items-that-get-added-and-removed-dynamically-which-approach-is-most-robust-for-handling-clicks-on-any-li","Q6. A ",[22,629,630],{},"\u003Cul>"," contains 500 ",[22,633,634],{},"\u003Cli>"," items that get added and removed dynamically. Which approach is most robust for handling clicks on any ",[22,637,634],{},[35,639,641,653,675,691],{"className":640},[38],[40,642,644,646,647,649,650,652],{"className":643},[43],[45,645],{"disabled":47,"type":48}," Attach a separate ",[22,648,369],{}," listener to every ",[22,651,634],{}," when it's created",[40,654,656,658,659,661,662,664,665,667,668,671,672,674],{"className":655},[43],[45,657],{"disabled":47,"type":48}," Attach a single ",[22,660,369],{}," listener to the ",[22,663,630],{}," and inspect ",[22,666,161],{}," (or use ",[22,669,670],{},".closest()",") to determine which ",[22,673,634],{}," was clicked",[40,676,678,680,681,684,685,687,688,690],{"className":677},[43],[45,679],{"disabled":47,"type":48}," Use ",[22,682,683],{},"element.onclick"," on each ",[22,686,634],{}," instead of ",[22,689,178],{}," since it's faster",[40,692,694,696,697,700,701,703],{"className":693},[43],[45,695],{"disabled":47,"type":48}," Poll ",[22,698,699],{},"document.activeElement"," on an interval to detect which ",[22,702,634],{}," was interacted with",[87,705,706,708,723],{},[90,707,92],{},[94,709,710,712,713,661,715,664,717,667,719,671,721,674],{},[97,711,99],{}," B — Attach a single ",[22,714,369],{},[22,716,630],{},[22,718,161],{},[22,720,670],{},[22,722,634],{},[94,724,725,727,728,175,731,733,734,737],{},[97,726,109],{}," This is event delegation: because clicks bubble up from any descendant, one listener on a stable ancestor catches interactions from every current ",[433,729,730],{},"and future",[22,732,634],{},", with no per-item wiring or cleanup needed when rows are added or removed. Option A requires re-attaching a listener on every re-render and doesn't scale to large or frequently-changing lists. Option C is false — ",[22,735,736],{},"onclick"," isn't inherently faster, and it still needs to be set per-element. Option D is unrelated to click detection and would miss most interactions entirely.",[14,739,740,748,846,867,926],{"language":196},[17,741,743,744,747],{"id":742},"q7-a-delegated-click-listener-on-a-ul-idlist-is-written-as","Q7. A delegated click listener on a ",[22,745,746],{},"\u003Cul id=\"list\">"," is written as:",[210,749,750],{"language":196},[213,751,753],{"className":215,"code":752,"language":196,"meta":217,"style":217},"list.addEventListener(\"click\", (event) => {\n  const item = event.target.closest(\"li[data-id]\");\n  if (!item) return;\n  console.log(\"Selected:\", item.dataset.id);\n});\n",[22,754,755,781,806,826,841],{"__ignoreMap":217},[221,756,757,760,762,764,766,769,773,776,778],{"class":223,"line":224},[221,758,759],{"class":227},"list.",[221,761,178],{"class":231},[221,763,234],{"class":227},[221,765,238],{"class":237},[221,767,768],{"class":227},", (",[221,770,772],{"class":771},"sCrzJ","event",[221,774,775],{"class":227},") ",[221,777,245],{"class":244},[221,779,780],{"class":227}," {\n",[221,782,783,786,789,792,795,798,800,803],{"class":223,"line":262},[221,784,785],{"class":244},"  const",[221,787,788],{"class":289}," item",[221,790,791],{"class":244}," =",[221,793,794],{"class":227}," event.target.",[221,796,797],{"class":231},"closest",[221,799,234],{"class":227},[221,801,802],{"class":237},"\"li[data-id]\"",[221,804,805],{"class":227},");\n",[221,807,808,811,814,817,820,823],{"class":223,"line":296},[221,809,810],{"class":244},"  if",[221,812,813],{"class":227}," (",[221,815,816],{"class":244},"!",[221,818,819],{"class":227},"item) ",[221,821,822],{"class":244},"return",[221,824,825],{"class":227},";\n",[221,827,828,831,833,835,838],{"class":223,"line":302},[221,829,830],{"class":227},"  console.",[221,832,251],{"class":231},[221,834,234],{"class":227},[221,836,837],{"class":237},"\"Selected:\"",[221,839,840],{"class":227},", item.dataset.id);\n",[221,842,843],{"class":223,"line":333},[221,844,845],{"class":227},"});\n",[94,847,848,849,852,853,856,857,860,861,863,864,866],{},"Each ",[22,850,851],{},"\u003Cli data-id=\"42\">"," contains a ",[22,854,855],{},"\u003Cbutton>\u003Cspan class=\"icon\">×\u003C\u002Fspan> Delete\u003C\u002Fbutton>",". A user clicks directly on the ",[22,858,859],{},"\u003Cspan class=\"icon\">",". Why is ",[22,862,670],{}," needed here instead of using ",[22,865,161],{}," directly?",[35,868,870,884,895,912],{"className":869},[38],[40,871,873,175,875,877,878,880,881,883],{"className":872},[43],[45,874],{"disabled":47,"type":48},[22,876,161],{}," is always the ",[22,879,634],{},", so ",[22,882,670],{}," is redundant",[40,885,887,175,889,891,892,894],{"className":886},[43],[45,888],{"disabled":47,"type":48},[22,890,670],{}," is required because ",[22,893,161],{}," does not exist inside delegated listeners",[40,896,898,175,900,902,903,905,906,908,909,911],{"className":897},[43],[45,899],{"disabled":47,"type":48},[22,901,161],{}," will be the innermost clicked element (the ",[22,904,24],{},"), not the ",[22,907,634],{},"; ",[22,910,670],{}," walks up from it to find the nearest matching ancestor (or itself)",[40,913,915,175,917,919,920,922,923,925],{"className":914},[43],[45,916],{"disabled":47,"type":48},[22,918,670],{}," searches the descendants of ",[22,921,161],{},", which is needed to find the ",[22,924,634],{},"'s children",[87,927,928,930,943],{},[90,929,92],{},[94,931,932,934,935,902,937,905,939,908,941,911],{},[97,933,99],{}," C — ",[22,936,161],{},[22,938,24],{},[22,940,634],{},[22,942,670],{},[94,944,945,947,948,950,951,953,954,957,958,961,962,965,966,968,969,971],{},[97,946,109],{}," In a delegated listener, ",[22,949,161],{}," is whatever the user actually clicked — frequently a deeply nested decorative element like an icon ",[22,952,24],{},", not the semantic row you actually care about. ",[22,955,956],{},".closest(selector)"," starts at the element itself (inclusive) and searches upward through ancestors for the first match, correctly landing on the ",[22,959,960],{},"\u003Cli data-id>"," no matter how deeply the click originated inside it. Option A is false — ",[22,963,964],{},"target"," is the deepest node, not the delegated container's child. Option B is false — ",[22,967,161],{}," always exists on the event object. Option D reverses the search direction; ",[22,970,670],{}," goes up the tree, never down into descendants.",[14,973,974,999,1036],{},[17,975,977,978,981,982,984,985,987,988,991,992,994,995,998],{"id":976},"q8-a-div-idouter-contains-a-nested-button-a-single-click-listener-is-attached-to-outer-when-a-user-clicks-the-button-inside-that-listener-eventtarget-and-eventcurrenttarget-are-compared-which-statement-is-correct","Q8. A ",[22,979,980],{},"\u003Cdiv id=\"outer\">"," contains a nested ",[22,983,448],{},". A single ",[22,986,369],{}," listener is attached to ",[22,989,990],{},"#outer",". When a user clicks the button, inside that listener ",[22,993,161],{}," and ",[22,996,997],{},"event.currentTarget"," are compared. Which statement is correct?",[35,1000,1002,1008,1019,1025],{"className":1001},[38],[40,1003,1005,1007],{"className":1004},[43],[45,1006],{"disabled":47,"type":48}," Both always refer to the div, since that's where the listener is attached",[40,1009,1011,175,1013,1015,1016,1018],{"className":1010},[43],[45,1012],{"disabled":47,"type":48},[22,1014,161],{}," is the div (the listener's element); ",[22,1017,997],{}," is the button (the clicked element)",[40,1020,1022,1024],{"className":1021},[43],[45,1023],{"disabled":47,"type":48}," Both always refer to the button, since that's what was clicked",[40,1026,1028,175,1030,1032,1033,1035],{"className":1027},[43],[45,1029],{"disabled":47,"type":48},[22,1031,161],{}," is the button (the element that actually triggered the event); ",[22,1034,997],{}," is the div (the element the listener is attached to) — the two stay fixed to their own definitions throughout the dispatch, and differ whenever the click originates on a descendant",[87,1037,1038,1040,1049],{},[90,1039,92],{},[94,1041,1042,1044,1045,1032,1047,1035],{},[97,1043,99],{}," D — ",[22,1046,161],{},[22,1048,997],{},[94,1050,1051,175,1053,1055,1056,1058,1059,1062,1063,1065,1066,1069,1070,1072],{},[97,1052,109],{},[22,1054,161],{}," is set once, at the very start of dispatch, to the innermost element the event originated on, and never changes for that dispatch. ",[22,1057,997],{}," instead tracks whichever element's listener is ",[433,1060,1061],{},"currently executing",", which changes as the event moves through capturing and bubbling — inside this listener it's always ",[22,1064,990],{},", since that's where the listener lives. This distinction matters when the same handler function is shared across multiple elements: ",[22,1067,1068],{},"currentTarget"," reliably tells you \"which element I'm attached to,\" while ",[22,1071,964],{}," tells you \"what was actually interacted with.\" Options A and B collapse this distinction incorrectly, and Option C wrongly assumes both track the clicked element.",[14,1074,1075,1079,1149,1152,1189],{"language":196},[17,1076,1078],{"id":1077},"q9-a-developer-writes","Q9. A developer writes:",[210,1080,1081],{"language":196},[213,1082,1084],{"className":215,"code":1083,"language":196,"meta":217,"style":217},"button.addEventListener(\"click\", () => console.log(\"clicked\"));\nbutton.removeEventListener(\"click\", () => console.log(\"clicked\"));\n\nbutton.click();\n",[22,1085,1086,1112,1137,1141],{"__ignoreMap":217},[221,1087,1088,1091,1093,1095,1097,1099,1101,1103,1105,1107,1110],{"class":223,"line":224},[221,1089,1090],{"class":227},"button.",[221,1092,178],{"class":231},[221,1094,234],{"class":227},[221,1096,238],{"class":237},[221,1098,241],{"class":227},[221,1100,245],{"class":244},[221,1102,248],{"class":227},[221,1104,251],{"class":231},[221,1106,234],{"class":227},[221,1108,1109],{"class":237},"\"clicked\"",[221,1111,259],{"class":227},[221,1113,1114,1116,1119,1121,1123,1125,1127,1129,1131,1133,1135],{"class":223,"line":262},[221,1115,1090],{"class":227},[221,1117,1118],{"class":231},"removeEventListener",[221,1120,234],{"class":227},[221,1122,238],{"class":237},[221,1124,241],{"class":227},[221,1126,245],{"class":244},[221,1128,248],{"class":227},[221,1130,251],{"class":231},[221,1132,234],{"class":227},[221,1134,1109],{"class":237},[221,1136,259],{"class":227},[221,1138,1139],{"class":223,"line":296},[221,1140,299],{"emptyLinePlaceholder":47},[221,1142,1143,1145,1147],{"class":223,"line":302},[221,1144,1090],{"class":227},[221,1146,369],{"class":231},[221,1148,372],{"class":227},[94,1150,1151],{},"What happens?",[35,1153,1155,1164,1173,1183],{"className":1154},[38],[40,1156,1158,1160,1161,1163],{"className":1157},[43],[45,1159],{"disabled":47,"type":48}," \"clicked\" logs once; the anonymous arrow function passed to ",[22,1162,1118],{}," is a different function reference, so nothing is actually removed",[40,1165,1167,1169,1170,1172],{"className":1166},[43],[45,1168],{"disabled":47,"type":48}," Nothing logs; ",[22,1171,1118],{}," successfully matches and removes the listener",[40,1174,1176,1178,1179,1182],{"className":1175},[43],[45,1177],{"disabled":47,"type":48}," It throws a ",[22,1180,1181],{},"TypeError"," because you can't remove a listener that hasn't fired yet",[40,1184,1186,1188],{"className":1185},[43],[45,1187],{"disabled":47,"type":48}," \"clicked\" logs twice, once for the add and once for the mismatched remove",[87,1190,1191,1193,1200],{},[90,1192,92],{},[94,1194,1195,1197,1198,1163],{},[97,1196,99],{}," A — \"clicked\" logs once; the anonymous arrow function passed to ",[22,1199,1118],{},[94,1201,1202,175,1204,175,1206,1208,1209,994,1212,1214,1215,1217,1218,1221,1222,1224],{},[97,1203,109],{},[97,1205,418],{},[22,1207,1118],{}," only removes a listener when it's called with the exact same function reference (plus matching ",[22,1210,1211],{},"type",[22,1213,186],{}," flag) that was originally passed to ",[22,1216,178],{},". Two separately-written arrow functions are never ",[22,1219,1220],{},"==="," to each other, even with byte-for-byte identical bodies, so the \"removal\" silently matches nothing and the original listener stays active — no error, no warning. To make a listener removable, store it in a named variable and pass that same reference to both calls. Option C invents an error that never occurs; ",[22,1223,1118],{}," fails silently on non-matches. Option D misunderstands that a non-matching remove call has zero effect on the listener count.",[14,1226,1227,1238,1265],{},[17,1228,1230,1231,1234,1235,1237],{"id":1229},"q10-what-does-passing-once-true-as-the-options-argument-to-addeventlistener-do","Q10. What does passing ",[22,1232,1233],{},"{ once: true }"," as the options argument to ",[22,1236,178],{}," do?",[35,1239,1241,1247,1253,1259],{"className":1240},[38],[40,1242,1244,1246],{"className":1243},[43],[45,1245],{"disabled":47,"type":48}," It makes the listener run once per animation frame, throttling rapid events",[40,1248,1250,1252],{"className":1249},[43],[45,1251],{"disabled":47,"type":48}," It automatically removes the listener after it has been invoked a single time",[40,1254,1256,1258],{"className":1255},[43],[45,1257],{"disabled":47,"type":48}," It prevents the event from bubbling after the first invocation",[40,1260,1262,1264],{"className":1261},[43],[45,1263],{"disabled":47,"type":48}," It defers the listener to run once the main thread is idle",[87,1266,1267,1269,1274],{},[90,1268,92],{},[94,1270,1271,1273],{},[97,1272,99],{}," B — It automatically removes the listener after it has been invoked a single time",[94,1275,1276,175,1278,1280,1281,1283,1284,1287,1288,1290,1291,1294,1295,1298],{},[97,1277,109],{},[22,1279,1233],{}," tells the browser to invoke the listener at most once, then internally call the equivalent of ",[22,1282,1118],{}," for it — useful for one-shot interactions like a dismiss button or a first-scroll trigger, without needing to manually clean up. Option A confuses it with ",[22,1285,1286],{},"requestAnimationFrame","-based throttling, an unrelated technique. Option C confuses it with ",[22,1289,32],{},". Option D confuses it with ",[22,1292,1293],{},"requestIdleCallback"," scheduling semantics, which ",[22,1296,1297],{},"once"," has nothing to do with.",[14,1300,1301,1305,1411,1417,1464],{"language":196},[17,1302,1304],{"id":1303},"q11-a-component-sets-up-several-listeners-tied-to-one-controller","Q11. A component sets up several listeners tied to one controller:",[210,1306,1307],{"language":196},[213,1308,1310],{"className":215,"code":1309,"language":196,"meta":217,"style":217},"const controller = new AbortController();\nconst { signal } = controller;\n\nbutton.addEventListener(\"click\", onClick, { signal });\nwindow.addEventListener(\"resize\", onResize, { signal });\ndocument.addEventListener(\"keydown\", onKeydown, { signal });\n\ncontroller.abort();\n",[22,1311,1312,1330,1349,1353,1366,1381,1396,1400],{"__ignoreMap":217},[221,1313,1314,1317,1320,1322,1325,1328],{"class":223,"line":224},[221,1315,1316],{"class":244},"const",[221,1318,1319],{"class":289}," controller",[221,1321,791],{"class":244},[221,1323,1324],{"class":244}," new",[221,1326,1327],{"class":231}," AbortController",[221,1329,372],{"class":227},[221,1331,1332,1334,1337,1340,1343,1346],{"class":223,"line":262},[221,1333,1316],{"class":244},[221,1335,1336],{"class":227}," { ",[221,1338,1339],{"class":289},"signal",[221,1341,1342],{"class":227}," } ",[221,1344,1345],{"class":244},"=",[221,1347,1348],{"class":227}," controller;\n",[221,1350,1351],{"class":223,"line":296},[221,1352,299],{"emptyLinePlaceholder":47},[221,1354,1355,1357,1359,1361,1363],{"class":223,"line":302},[221,1356,1090],{"class":227},[221,1358,178],{"class":231},[221,1360,234],{"class":227},[221,1362,238],{"class":237},[221,1364,1365],{"class":227},", onClick, { signal });\n",[221,1367,1368,1371,1373,1375,1378],{"class":223,"line":333},[221,1369,1370],{"class":227},"window.",[221,1372,178],{"class":231},[221,1374,234],{"class":227},[221,1376,1377],{"class":237},"\"resize\"",[221,1379,1380],{"class":227},", onResize, { signal });\n",[221,1382,1383,1386,1388,1390,1393],{"class":223,"line":359},[221,1384,1385],{"class":227},"document.",[221,1387,178],{"class":231},[221,1389,234],{"class":227},[221,1391,1392],{"class":237},"\"keydown\"",[221,1394,1395],{"class":227},", onKeydown, { signal });\n",[221,1397,1398],{"class":223,"line":364},[221,1399,299],{"emptyLinePlaceholder":47},[221,1401,1403,1406,1409],{"class":223,"line":1402},8,[221,1404,1405],{"class":227},"controller.",[221,1407,1408],{"class":231},"abort",[221,1410,372],{"class":227},[94,1412,1413,1414,33],{},"What is the effect of calling ",[22,1415,1416],{},"controller.abort()",[35,1418,1420,1430,1444,1452],{"className":1419},[38],[40,1421,1423,1425,1426,1429],{"className":1422},[43],[45,1424],{"disabled":47,"type":48}," Only the most recently added listener (",[22,1427,1428],{},"keydown",") is removed",[40,1431,1433,1435,1436,1439,1440,1443],{"className":1432},[43],[45,1434],{"disabled":47,"type":48}," Nothing — ",[22,1437,1438],{},"AbortController"," only cancels ",[22,1441,1442],{},"fetch"," requests, not event listeners",[40,1445,1447,1449,1450],{"className":1446},[43],[45,1448],{"disabled":47,"type":48}," All three listeners are removed simultaneously, since they all share the same ",[22,1451,1339],{},[40,1453,1455,1457,1458,1460,1461,1463],{"className":1454},[43],[45,1456],{"disabled":47,"type":48}," It throws because ",[22,1459,1339],{}," can only be used with one ",[22,1462,178],{}," call at a time",[87,1465,1466,1468,1475],{},[90,1467,92],{},[94,1469,1470,1472,1473],{},[97,1471,99],{}," C — All three listeners are removed simultaneously, since they all share the same ",[22,1474,1339],{},[94,1476,1477,1479,1480,1482,1483,1485,1486,1488,1489,1492,1493,1495,1496,1499,1500,1502,1503,1505],{},[97,1478,109],{}," Modern ",[22,1481,178],{}," accepts a ",[22,1484,1339],{}," option, and a single ",[22,1487,1438],{}," can be shared across any number of listeners on any number of elements. Calling ",[22,1490,1491],{},"abort()"," once removes every listener registered with that signal in one shot, replacing the older pattern of manually calling ",[22,1494,1118],{}," for each one with matching references. Option B is outdated — ",[22,1497,1498],{},"AbortSignal"," is now a general-purpose cancellation primitive used by ",[22,1501,1442],{},", ",[22,1504,178],{},", and other APIs. Options A and D misdescribe the sharing behavior; nothing limits a signal to a single listener.",[14,1507,1508,1526,1553],{},[17,1509,1511,1512,1515,1516,1519,1520,1523,1524,33],{"id":1510},"q12-why-would-you-add-passive-true-to-a-touchstart-or-wheel-event-listener-that-never-calls-preventdefault","Q12. Why would you add ",[22,1513,1514],{},"{ passive: true }"," to a ",[22,1517,1518],{},"touchstart"," or ",[22,1521,1522],{},"wheel"," event listener that never calls ",[22,1525,608],{},[35,1527,1529,1535,1541,1547],{"className":1528},[38],[40,1530,1532,1534],{"className":1531},[43],[45,1533],{"disabled":47,"type":48}," It makes the listener fire before capturing-phase listeners",[40,1536,1538,1540],{"className":1537},[43],[45,1539],{"disabled":47,"type":48}," It automatically debounces rapid touch\u002Fwheel events for you",[40,1542,1544,1546],{"className":1543},[43],[45,1545],{"disabled":47,"type":48}," It silently ignores any code inside the handler",[40,1548,1550,1552],{"className":1549},[43],[45,1551],{"disabled":47,"type":48}," It tells the browser it can start scrolling immediately without waiting to see if the handler cancels it, improving scroll smoothness",[87,1554,1555,1557,1562],{},[90,1556,92],{},[94,1558,1559,1561],{},[97,1560,99],{}," D — It tells the browser it can start scrolling immediately without waiting to see if the handler cancels it, improving scroll smoothness",[94,1563,1564,175,1566,1569,1570,1572,1573,1575,1576,1578,1579,615,1581,1584,1585,1588,1589,1591],{},[97,1565,109],{},[97,1567,1568],{},"Performance."," Normally the browser must wait for a touch\u002Fwheel handler to finish running — in case it calls ",[22,1571,608],{}," to cancel native scrolling — before it can start scrolling, which can cause visible jank if the main thread is busy. ",[22,1574,1514],{}," is a promise that the handler will never call ",[22,1577,608],{},", letting the browser begin the native scroll or fling in parallel immediately. Some browsers even default ",[22,1580,1518],{},[22,1582,1583],{},"touchmove"," listeners to passive for exactly this reason. Options B and C describe behaviors ",[22,1586,1587],{},"passive"," doesn't have. Option A confuses it with the unrelated ",[22,1590,186],{}," option.",[14,1593,1594,1598,1664,1667,1709],{"language":196},[17,1595,1597],{"id":1596},"q13-a-listener-is-registered-like-this","Q13. A listener is registered like this:",[210,1599,1600],{"language":196},[213,1601,1603],{"className":215,"code":1602,"language":196,"meta":217,"style":217},"document.addEventListener(\n  \"touchstart\",\n  (event) => {\n    event.preventDefault();\n  },\n  { passive: true }\n);\n",[22,1604,1605,1614,1622,1635,1645,1650,1660],{"__ignoreMap":217},[221,1606,1607,1609,1611],{"class":223,"line":224},[221,1608,1385],{"class":227},[221,1610,178],{"class":231},[221,1612,1613],{"class":227},"(\n",[221,1615,1616,1619],{"class":223,"line":262},[221,1617,1618],{"class":237},"  \"touchstart\"",[221,1620,1621],{"class":227},",\n",[221,1623,1624,1627,1629,1631,1633],{"class":223,"line":296},[221,1625,1626],{"class":227},"  (",[221,1628,772],{"class":771},[221,1630,775],{"class":227},[221,1632,245],{"class":244},[221,1634,780],{"class":227},[221,1636,1637,1640,1643],{"class":223,"line":302},[221,1638,1639],{"class":227},"    event.",[221,1641,1642],{"class":231},"preventDefault",[221,1644,372],{"class":227},[221,1646,1647],{"class":223,"line":333},[221,1648,1649],{"class":227},"  },\n",[221,1651,1652,1655,1657],{"class":223,"line":359},[221,1653,1654],{"class":227},"  { passive: ",[221,1656,290],{"class":289},[221,1658,1659],{"class":227}," }\n",[221,1661,1662],{"class":223,"line":364},[221,1663,805],{"class":227},[94,1665,1666],{},"What happens when a user touches the screen?",[35,1668,1670,1678,1686,1698],{"className":1669},[38],[40,1671,1673,175,1675,1677],{"className":1672},[43],[45,1674],{"disabled":47,"type":48},[22,1676,608],{}," is silently ignored (default scrolling still happens), and most browsers log a console warning",[40,1679,1681,175,1683,1685],{"className":1680},[43],[45,1682],{"disabled":47,"type":48},[22,1684,608],{}," successfully blocks the default touch behavior (e.g., scrolling)",[40,1687,1689,1691,1692,1694,1695,1697],{"className":1688},[43],[45,1690],{"disabled":47,"type":48}," The listener throws a ",[22,1693,1181],{}," because ",[22,1696,1642],{}," is disabled on passive listeners",[40,1699,1701,1703,1704,994,1706,1708],{"className":1700},[43],[45,1702],{"disabled":47,"type":48}," The event stops firing entirely because ",[22,1705,1587],{},[22,1707,1642],{}," conflict",[87,1710,1711,1713,1720],{},[90,1712,92],{},[94,1714,1715,1717,1718,1677],{},[97,1716,99],{}," A — ",[22,1719,608],{},[94,1721,1722,175,1724,175,1726,1728,1729,1731],{},[97,1723,109],{},[97,1725,418],{},[22,1727,1514],{}," is a contract with the browser that the listener will never cancel the default action. Calling ",[22,1730,608],{}," inside it doesn't throw, but the call becomes a no-op — the browser has already committed to proceeding with the default scroll without waiting, so nothing is actually blocked. Most browsers (e.g., Chrome) log a console warning such as \"Unable to preventDefault inside passive event listener\" to surface the mistake. Option C overstates the failure mode — it's silent, not an exception. Option D is wrong; the rest of the handler's code still runs, only the cancellation is dropped.",[14,1733,1734,1746,1855,1858,1931],{"language":196},[17,1735,1737,1738,1741,1742,1745],{"id":1736},"q14-given-child-is-a-descendant-of-parent","Q14. Given ",[22,1739,1740],{},"child"," is a descendant of ",[22,1743,1744],{},"parent",":",[210,1747,1748],{"language":196},[213,1749,1751],{"className":215,"code":1750,"language":196,"meta":217,"style":217},"parent.addEventListener(\"cart:updated\", (e) => {\n  console.log(e.detail.itemCount);\n});\n\nconst event = new CustomEvent(\"cart:updated\", {\n  detail: { itemCount: 3 },\n  bubbles: true,\n});\n\nchild.dispatchEvent(event);\n",[22,1752,1753,1776,1785,1789,1793,1814,1825,1834,1838,1843],{"__ignoreMap":217},[221,1754,1755,1758,1760,1762,1765,1767,1770,1772,1774],{"class":223,"line":224},[221,1756,1757],{"class":227},"parent.",[221,1759,178],{"class":231},[221,1761,234],{"class":227},[221,1763,1764],{"class":237},"\"cart:updated\"",[221,1766,768],{"class":227},[221,1768,1769],{"class":771},"e",[221,1771,775],{"class":227},[221,1773,245],{"class":244},[221,1775,780],{"class":227},[221,1777,1778,1780,1782],{"class":223,"line":262},[221,1779,830],{"class":227},[221,1781,251],{"class":231},[221,1783,1784],{"class":227},"(e.detail.itemCount);\n",[221,1786,1787],{"class":223,"line":296},[221,1788,845],{"class":227},[221,1790,1791],{"class":223,"line":302},[221,1792,299],{"emptyLinePlaceholder":47},[221,1794,1795,1797,1800,1802,1804,1807,1809,1811],{"class":223,"line":333},[221,1796,1316],{"class":244},[221,1798,1799],{"class":289}," event",[221,1801,791],{"class":244},[221,1803,1324],{"class":244},[221,1805,1806],{"class":231}," CustomEvent",[221,1808,234],{"class":227},[221,1810,1764],{"class":237},[221,1812,1813],{"class":227},", {\n",[221,1815,1816,1819,1822],{"class":223,"line":359},[221,1817,1818],{"class":227},"  detail: { itemCount: ",[221,1820,1821],{"class":289},"3",[221,1823,1824],{"class":227}," },\n",[221,1826,1827,1830,1832],{"class":223,"line":364},[221,1828,1829],{"class":227},"  bubbles: ",[221,1831,290],{"class":289},[221,1833,1621],{"class":227},[221,1835,1836],{"class":223,"line":1402},[221,1837,845],{"class":227},[221,1839,1841],{"class":223,"line":1840},9,[221,1842,299],{"emptyLinePlaceholder":47},[221,1844,1846,1849,1852],{"class":223,"line":1845},10,[221,1847,1848],{"class":227},"child.",[221,1850,1851],{"class":231},"dispatchEvent",[221,1853,1854],{"class":227},"(event);\n",[94,1856,1857],{},"What logs?",[35,1859,1861,1873,1894,1914],{"className":1860},[38],[40,1862,1864,1435,1866,1869,1870,1872],{"className":1863},[43],[45,1865],{"disabled":47,"type":48},[22,1867,1868],{},"CustomEvent"," instances never trigger ",[22,1871,178],{}," listeners",[40,1874,1876,175,1878,1880,1881,1883,1884,1887,1888,1890,1891],{"className":1875},[43],[45,1877],{"disabled":47,"type":48},[22,1879,1821],{}," — the event was dispatched on ",[22,1882,1740],{},", and because ",[22,1885,1886],{},"bubbles: true"," was set, it propagates up to the ",[22,1889,1744],{}," listener, which reads it via ",[22,1892,1893],{},"e.detail",[40,1895,1897,175,1899,1902,1903,1906,1907,1910,1911],{"className":1896},[43],[45,1898],{"disabled":47,"type":48},[22,1900,1901],{},"undefined"," — ",[22,1904,1905],{},"detail"," is only accessible via ",[22,1908,1909],{},"event.data",", not ",[22,1912,1913],{},"event.detail",[40,1915,1917,1919,1920,1902,1922,1924,1925,1927,1928],{"className":1916},[43],[45,1918],{"disabled":47,"type":48}," A ",[22,1921,1181],{},[22,1923,1851],{}," cannot be used with a ",[22,1926,1868],{},", only with built-in events like ",[22,1929,1930],{},"Event",[87,1932,1933,1935,1950],{},[90,1934,92],{},[94,1936,1937,1939,1940,1880,1942,1883,1944,1887,1946,1890,1948],{},[97,1938,99],{}," B — ",[22,1941,1821],{},[22,1943,1740],{},[22,1945,1886],{},[22,1947,1744],{},[22,1949,1893],{},[94,1951,1952,175,1954,1956,1957,1959,1960,1962,1963,1965,1966,1968,1969,1972,1973,1975,1976,1978,1979,1981,1982,1984,1985,1987,1988,1990,1991,1993],{},[97,1953,109],{},[22,1955,1868],{}," lets application code build its own named events carrying an arbitrary payload in ",[22,1958,1905],{},", and ",[22,1961,1851],{}," runs it through the exact same capture\u002Ftarget\u002Fbubble pipeline as a real user-triggered event. Note the gotcha: unlike most native UI events (which bubble by default), ",[22,1964,1868],{}," (like the base ",[22,1967,1930],{}," constructor) defaults ",[22,1970,1971],{},"bubbles"," to ",[22,1974,182],{}," — it had to be explicitly set to ",[22,1977,290],{}," here for ",[22,1980,1744],{},"'s listener to ever see it. Option A is wrong — ",[22,1983,1851],{}," synchronously invokes any matching listeners. Option C invents a nonexistent property name. Option D is false; ",[22,1986,1851],{}," accepts any ",[22,1989,1930],{}," subtype, including ",[22,1992,1868],{},".",[14,1995,1996,2004,2050],{},[17,1997,1999,2000,2003],{"id":1998},"q15-a-team-wants-to-detect-when-focus-leaves-a-forms-container-entirely-using-event-delegation-with-a-single-listener-on-the-form-element-which-event-should-they-use-and-why","Q15. A team wants to detect when focus leaves a form's container entirely, using event delegation with a single listener on the ",[22,2001,2002],{},"\u003Cform>"," element. Which event should they use, and why?",[35,2005,2007,2016,2027,2039],{"className":2006},[38],[40,2008,2010,175,2012,2015],{"className":2009},[43],[45,2011],{"disabled":47,"type":48},[22,2013,2014],{},"blur",", because it fires on the form itself whenever any child input loses focus",[40,2017,2019,175,2021,2024,2025],{"className":2018},[43],[45,2020],{"disabled":47,"type":48},[22,2022,2023],{},"focus",", because it's the bubbling counterpart to ",[22,2026,2014],{},[40,2028,2030,175,2032,2035,2036,2038],{"className":2029},[43],[45,2031],{"disabled":47,"type":48},[22,2033,2034],{},"focusout",", because unlike ",[22,2037,2014],{},", it bubbles, so a single listener on the form catches focus changes from any descendant input",[40,2040,2042,2044,2045,1519,2047,2049],{"className":2041},[43],[45,2043],{"disabled":47,"type":48}," Either ",[22,2046,2014],{},[22,2048,2034],{}," work identically for delegation; the choice is just style preference",[87,2051,2052,2054,2062],{},[90,2053,92],{},[94,2055,2056,934,2058,2035,2060,2038],{},[97,2057,99],{},[22,2059,2034],{},[22,2061,2014],{},[94,2063,2064,175,2066,175,2068,994,2070,2072,2073,994,2076,2078,2079,2081,2082,2084,2085,2087,2088,2090],{},[97,2065,109],{},[97,2067,418],{},[22,2069,2023],{},[22,2071,2014],{}," do not bubble by design, so a listener on a container only fires when that exact container element gains or loses focus — not its descendants. ",[22,2074,2075],{},"focusin",[22,2077,2034],{}," are the bubbling equivalents, standardized specifically to support delegation, and are the correct choice here. Option A is the classic mistake: ",[22,2080,2014],{}," on the form fires only if the ",[22,2083,2002],{}," element itself is directly focused, which rarely happens. Option B confuses ",[22,2086,2023],{}," (non-bubbling) with ",[22,2089,2075],{},". Option D is false — the two behave completely differently for delegation.",[14,2092,2093,2108,2154],{},[17,2094,2096,2097,2100,2101,2100,2104,2107],{"id":2095},"q16-a-script-runs-in-order-btnonclick-fna-then-btnonclick-fnb-then-btnaddeventlistenerclick-fnc-when-the-button-is-clicked-which-handlers-run-and-in-what-order","Q16. A script runs, in order: ",[22,2098,2099],{},"btn.onclick = fnA;"," then ",[22,2102,2103],{},"btn.onclick = fnB;",[22,2105,2106],{},"btn.addEventListener(\"click\", fnC)",". When the button is clicked, which handlers run, and in what order?",[35,2109,2111,2117,2129,2142],{"className":2110},[38],[40,2112,2114,2116],{"className":2113},[43],[45,2115],{"disabled":47,"type":48}," fnA, then fnB, then fnC — all three coexist because they were assigned at different times",[40,2118,2120,2122,2123,2125,2126,2128],{"className":2119},[43],[45,2121],{"disabled":47,"type":48}," fnC, then fnB — ",[22,2124,178],{},"-registered handlers always run before the ",[22,2127,736],{}," property",[40,2130,2132,1919,2134,2136,2137,994,2139,2141],{"className":2131},[43],[45,2133],{"disabled":47,"type":48},[22,2135,1181],{}," is thrown — ",[22,2138,736],{},[22,2140,178],{}," cannot both be used on the same element",[40,2143,2145,2147,2148,2150,2151,2153],{"className":2144},[43],[45,2146],{"disabled":47,"type":48}," fnB, then fnC — the second assignment to ",[22,2149,736],{}," silently overwrites the first (fnA never runs), while ",[22,2152,178],{}," maintains its own independent list and runs alongside it",[87,2155,2156,2158,2167],{},[90,2157,92],{},[94,2159,2160,2162,2163,2150,2165,2153],{},[97,2161,99],{}," D — fnB, then fnC — the second assignment to ",[22,2164,736],{},[22,2166,178],{},[94,2168,2169,175,2171,175,2173,2175,2176,2179,2180,2183,2184,2186,2187,2189,2190,2192],{},[97,2170,109],{},[97,2172,418],{},[22,2174,683],{}," is a plain property, not a collection — each assignment simply replaces whatever function was stored there, so only ",[22,2177,2178],{},"fnB"," (the last assignment) survives, with no error or warning that ",[22,2181,2182],{},"fnA"," was discarded. ",[22,2185,178],{}," maintains a completely separate internal list of listeners that can hold any number of handlers without clobbering the ",[22,2188,736],{}," property or each other. Option A wrongly assumes property assignment stacks like ",[22,2191,178],{}," does. Option B invents a precedence rule that doesn't exist. Option C is false — the two mechanisms coexist without conflict.",[14,2194,2195,2199,2275,2281,2316],{"language":196},[17,2196,2198],{"id":2197},"q17-given","Q17. Given:",[210,2200,2201],{"language":196},[213,2202,2204],{"className":215,"code":2203,"language":196,"meta":217,"style":217},"function handleClick() {\n  console.log(\"clicked\");\n}\n\nbutton.addEventListener(\"click\", handleClick);\nbutton.addEventListener(\"click\", handleClick);\n\nbutton.click();\n",[22,2205,2206,2217,2229,2234,2238,2251,2263,2267],{"__ignoreMap":217},[221,2207,2208,2211,2214],{"class":223,"line":224},[221,2209,2210],{"class":244},"function",[221,2212,2213],{"class":231}," handleClick",[221,2215,2216],{"class":227},"() {\n",[221,2218,2219,2221,2223,2225,2227],{"class":223,"line":262},[221,2220,830],{"class":227},[221,2222,251],{"class":231},[221,2224,234],{"class":227},[221,2226,1109],{"class":237},[221,2228,805],{"class":227},[221,2230,2231],{"class":223,"line":296},[221,2232,2233],{"class":227},"}\n",[221,2235,2236],{"class":223,"line":302},[221,2237,299],{"emptyLinePlaceholder":47},[221,2239,2240,2242,2244,2246,2248],{"class":223,"line":333},[221,2241,1090],{"class":227},[221,2243,178],{"class":231},[221,2245,234],{"class":227},[221,2247,238],{"class":237},[221,2249,2250],{"class":227},", handleClick);\n",[221,2252,2253,2255,2257,2259,2261],{"class":223,"line":359},[221,2254,1090],{"class":227},[221,2256,178],{"class":231},[221,2258,234],{"class":227},[221,2260,238],{"class":237},[221,2262,2250],{"class":227},[221,2264,2265],{"class":223,"line":364},[221,2266,299],{"emptyLinePlaceholder":47},[221,2268,2269,2271,2273],{"class":223,"line":1402},[221,2270,1090],{"class":227},[221,2272,369],{"class":231},[221,2274,372],{"class":227},[94,2276,2277,2278,2280],{},"How many times does ",[22,2279,1109],{}," log?",[35,2282,2284,2293,2302,2308],{"className":2283},[38],[40,2285,2287,2289,2290,2292],{"className":2286},[43],[45,2288],{"disabled":47,"type":48}," Once — ",[22,2291,178],{}," silently ignores a call that has the same type, function reference, and capture\u002Foptions as one already registered",[40,2294,2296,2298,2299,2301],{"className":2295},[43],[45,2297],{"disabled":47,"type":48}," Twice — each ",[22,2300,178],{}," call registers an independent listener",[40,2303,2305,2307],{"className":2304},[43],[45,2306],{"disabled":47,"type":48}," Zero — registering the same listener twice throws and prevents both from being added",[40,2309,2311,2313,2314],{"className":2310},[43],[45,2312],{"disabled":47,"type":48}," Twice, but only if the second call includes ",[22,2315,1233],{},[87,2317,2318,2320,2327],{},[90,2319,92],{},[94,2321,2322,2324,2325,2292],{},[97,2323,99],{}," A — Once — ",[22,2326,178],{},[94,2328,2329,175,2331,2333,2334,2336,2337,2339,2340,2342,2343,2346,2347,2349,2350,2352,2353,2356],{},[97,2330,109],{},[97,2332,418],{}," Per spec, a call to ",[22,2335,178],{}," is treated as a no-op duplicate — and simply skipped — only when the event ",[22,2338,1211],{},", the exact function reference, and the ",[22,2341,186],{}," flag all match an entry already registered on that element; here all three match ",[22,2344,2345],{},"handleClick",", so the second call adds nothing and ",[22,2348,1109],{}," logs once. This surprises developers who assume every call adds a new entry. It stops being a duplicate the moment any of the three differs — e.g., a different ",[22,2351,186],{}," value, or a fresh arrow function created on each call, which is exactly why inline anonymous handlers ",[433,2354,2355],{},"do"," get registered multiple times. Option B is the natural-but-wrong assumption; Option C invents an error that never happens.",[14,2358,2359,2386,2435],{},[17,2360,2362,2363,2366,2367,2370,2371,2374,2375,2378,2379,2382,2383,2385],{"id":2361},"q18-a-single-page-app-renders-a-large-canvas-chart-and-attaches-chartcanvasaddeventlistenermousemove-handlehover-where-handlehover-closes-over-a-large-dataset-array-when-the-user-navigates-away-the-component-removes-the-canvas-from-the-dom-via-chartcanvasremove-but-never-calls-removeeventlistener-whats-the-consequence","Q18. A single-page app renders a large ",[22,2364,2365],{},"\u003Ccanvas>"," chart and attaches ",[22,2368,2369],{},"chartCanvas.addEventListener(\"mousemove\", handleHover)",", where ",[22,2372,2373],{},"handleHover"," closes over a large ",[22,2376,2377],{},"dataset"," array. When the user navigates away, the component removes the canvas from the DOM via ",[22,2380,2381],{},"chartCanvas.remove()"," but never calls ",[22,2384,1118],{},". What's the consequence?",[35,2387,2389,2395,2414,2424],{"className":2388},[38],[40,2390,2392,2394],{"className":2391},[43],[45,2393],{"disabled":47,"type":48}," None — once an element is detached from the DOM, all of its event listeners and closures are automatically garbage collected",[40,2396,2398,2400,2401,2404,2405,2407,2408,2410,2411,2413],{"className":2397},[43],[45,2399],{"disabled":47,"type":48}," The ",[22,2402,2403],{},"chartCanvas"," element — and the ",[22,2406,2377],{}," array ",[22,2409,2373],{}," closes over — can be kept alive in memory as long as something still references ",[22,2412,2403],{}," or the listener, even though it's no longer visible on the page",[40,2415,2417,2419,2420,2423],{"className":2416},[43],[45,2418],{"disabled":47,"type":48}," The browser throws an error on the next ",[22,2421,2422],{},"mousemove"," because the element is detached",[40,2425,2427,175,2429,2431,2432,2434],{"className":2426},[43],[45,2428],{"disabled":47,"type":48},[22,2430,2373],{}," stops being called, but ",[22,2433,2377],{}," is freed immediately regardless of other references",[87,2436,2437,2439,2452],{},[90,2438,92],{},[94,2440,2441,2443,2444,2404,2446,2407,2448,2410,2450,2413],{},[97,2442,99],{}," B — The ",[22,2445,2403],{},[22,2447,2377],{},[22,2449,2373],{},[22,2451,2403],{},[94,2453,2454,175,2456,2458,2459,2461,2462,2464,2465,1959,2467,2469,2470,2472,2473,2475,2476,2478],{},[97,2455,109],{},[97,2457,1568],{}," Removing an element from the DOM does not make it eligible for garbage collection by itself — reclamation only happens once nothing reachable still references it. If ",[22,2460,2373],{}," (and its closure over ",[22,2463,2377],{},") is still attached to ",[22,2466,2403],{},[22,2468,2403],{}," itself is still referenced anywhere (a variable, a cache, another closure), the whole chain — including the large ",[22,2471,2377],{}," array — stays resident in memory, invisible on the page but present in the heap. This is the classic \"detached DOM node\" leak, visible in DevTools' heap snapshot tool. The fix is to call ",[22,2474,1118],{}," (or use a shared ",[22,2477,1438],{},") before or when discarding the element. Option A is the false assumption most developers make. Options C and D describe behavior that doesn't occur — detached elements keep functioning normally as long as they're referenced, and nothing is freed just because rendering stopped.",[14,2480,2481,2485,2525],{},[17,2482,2484],{"id":2483},"q19-a-table-renders-10000-rows-each-with-a-delete-button-and-rows-are-frequently-added-and-removed-via-re-renders-which-listener-strategy-is-best-practice-and-why","Q19. A table renders 10,000 rows, each with a \"Delete\" button, and rows are frequently added and removed via re-renders. Which listener strategy is best practice, and why?",[35,2486,2488,2497,2507,2517],{"className":2487},[38],[40,2489,2491,2493,2494,2496],{"className":2490},[43],[45,2492],{"disabled":47,"type":48}," Attach one ",[22,2495,178],{}," to each \"Delete\" button — it's the most explicit and easiest to reason about",[40,2498,2500,2502,2503,2506],{"className":2499},[43],[45,2501],{"disabled":47,"type":48}," Use inline ",[22,2504,2505],{},"onclick=\"...\""," HTML attributes on each button so there's no JS wiring needed",[40,2508,2510,2512,2513,2516],{"className":2509},[43],[45,2511],{"disabled":47,"type":48}," Attach a single listener to the table (or its container) and use ",[22,2514,2515],{},"event.target.closest(\"button\")"," to identify the clicked row — avoids thousands of listener objects and needs no rewiring when rows change",[40,2518,2520,680,2522,2524],{"className":2519},[43],[45,2521],{"disabled":47,"type":48},[22,2523,1233],{}," on each button's listener so memory is automatically reclaimed after the first click",[87,2526,2527,2529,2536],{},[90,2528,92],{},[94,2530,2531,2533,2534,2516],{},[97,2532,99],{}," C — Attach a single listener to the table (or its container) and use ",[22,2535,2515],{},[94,2537,2538,175,2540,2542,2543,2546],{},[97,2539,109],{},[97,2541,1568],{}," With 10,000 per-row listeners, both memory and setup cost scale linearly with row count, and every re-render that adds or removes rows must carefully add\u002Fremove matching listeners or risk leaking them. A single delegated listener on a stable ancestor costs one listener object regardless of row count, automatically covers rows added later (bubbling doesn't care when a descendant was created), and needs zero cleanup when rows are removed. Option A is exactly the anti-pattern delegation exists to solve. Option B mixes markup with behavior, supports only one handler per element, and still costs one binding per row. Option D is irrelevant — ",[22,2544,2545],{},"once: true"," only affects a single button's own first click and does nothing to address the scaling problem.",[14,2548,2549,2558,2691,2693,2728],{"language":196},[17,2550,2552,2553,2555,2556,1745],{"id":2551},"q20-given-child-is-nested-inside-parent","Q20. Given ",[22,2554,1740],{}," is nested inside ",[22,2557,1744],{},[210,2559,2560],{"language":196},[213,2561,2563],{"className":215,"code":2562,"language":196,"meta":217,"style":217},"child.addEventListener(\"click\", (e) => {\n  console.log(\"child A\");\n  e.stopImmediatePropagation();\n});\nchild.addEventListener(\"click\", () => {\n  console.log(\"child B\");\n});\nparent.addEventListener(\"click\", () => {\n  console.log(\"parent\");\n});\n\nchild.click();\n",[22,2564,2565,2585,2598,2607,2611,2627,2640,2644,2660,2673,2677,2682],{"__ignoreMap":217},[221,2566,2567,2569,2571,2573,2575,2577,2579,2581,2583],{"class":223,"line":224},[221,2568,1848],{"class":227},[221,2570,178],{"class":231},[221,2572,234],{"class":227},[221,2574,238],{"class":237},[221,2576,768],{"class":227},[221,2578,1769],{"class":771},[221,2580,775],{"class":227},[221,2582,245],{"class":244},[221,2584,780],{"class":227},[221,2586,2587,2589,2591,2593,2596],{"class":223,"line":262},[221,2588,830],{"class":227},[221,2590,251],{"class":231},[221,2592,234],{"class":227},[221,2594,2595],{"class":237},"\"child A\"",[221,2597,805],{"class":227},[221,2599,2600,2603,2605],{"class":223,"line":296},[221,2601,2602],{"class":227},"  e.",[221,2604,462],{"class":231},[221,2606,372],{"class":227},[221,2608,2609],{"class":223,"line":302},[221,2610,845],{"class":227},[221,2612,2613,2615,2617,2619,2621,2623,2625],{"class":223,"line":333},[221,2614,1848],{"class":227},[221,2616,178],{"class":231},[221,2618,234],{"class":227},[221,2620,238],{"class":237},[221,2622,241],{"class":227},[221,2624,245],{"class":244},[221,2626,780],{"class":227},[221,2628,2629,2631,2633,2635,2638],{"class":223,"line":359},[221,2630,830],{"class":227},[221,2632,251],{"class":231},[221,2634,234],{"class":227},[221,2636,2637],{"class":237},"\"child B\"",[221,2639,805],{"class":227},[221,2641,2642],{"class":223,"line":364},[221,2643,845],{"class":227},[221,2645,2646,2648,2650,2652,2654,2656,2658],{"class":223,"line":1402},[221,2647,1757],{"class":227},[221,2649,178],{"class":231},[221,2651,234],{"class":227},[221,2653,238],{"class":237},[221,2655,241],{"class":227},[221,2657,245],{"class":244},[221,2659,780],{"class":227},[221,2661,2662,2664,2666,2668,2671],{"class":223,"line":1840},[221,2663,830],{"class":227},[221,2665,251],{"class":231},[221,2667,234],{"class":227},[221,2669,2670],{"class":237},"\"parent\"",[221,2672,805],{"class":227},[221,2674,2675],{"class":223,"line":1845},[221,2676,845],{"class":227},[221,2678,2680],{"class":223,"line":2679},11,[221,2681,299],{"emptyLinePlaceholder":47},[221,2683,2685,2687,2689],{"class":223,"line":2684},12,[221,2686,1848],{"class":227},[221,2688,369],{"class":231},[221,2690,372],{"class":227},[94,2692,1857],{},[35,2694,2696,2702,2708,2714],{"className":2695},[38],[40,2697,2699,2701],{"className":2698},[43],[45,2700],{"disabled":47,"type":48}," child A, child B, parent",[40,2703,2705,2707],{"className":2704},[43],[45,2706],{"disabled":47,"type":48}," child A, parent — sibling listeners on the same element aren't affected, only propagation is stopped",[40,2709,2711,2713],{"className":2710},[43],[45,2712],{"disabled":47,"type":48}," child B, parent — listeners run in reverse registration order, so B always wins the race before A calls stop",[40,2715,2717,2719,2720,2722,2723,2725,2726],{"className":2716},[43],[45,2718],{"disabled":47,"type":48}," child A only — ",[22,2721,505],{}," cancels both the remaining sibling listener on ",[22,2724,1740],{}," and propagation up to ",[22,2727,1744],{},[87,2729,2730,2732,2743],{},[90,2731,92],{},[94,2733,2734,2736,2737,2722,2739,2725,2741],{},[97,2735,99],{}," D — child A only — ",[22,2738,505],{},[22,2740,1740],{},[22,2742,1744],{},[94,2744,2745,175,2747,175,2749,2751,2752,2754,2755,2757,2758,2760,2761,2763,2764,2766],{},[97,2746,109],{},[97,2748,418],{},[22,2750,505],{}," is the strictest of the three propagation controls: like ",[22,2753,32],{},", it halts further travel to ancestors, but it additionally prevents any other listener still queued on the ",[433,2756,531],{}," element from running at all. Since \"child A\" runs first (listeners fire in registration order) and calls it immediately, \"child B\" never fires, and the event never reaches ",[22,2759,1744],{},"'s listener either. Option A ignores that ",[22,2762,505],{}," was called. Option B describes plain ",[22,2765,32],{},"'s behavior, not the stricter method actually used here — the exact distinction this question tests. Option C invents a \"reverse order\" execution rule that doesn't exist; listeners always run in the order they were registered.",[2768,2769,2770],"style",{},"html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":217,"searchDepth":262,"depth":262,"links":2772},[2773,2775,2777,2779,2781,2783,2785,2787,2789,2790,2792,2793,2795,2796,2798,2800,2802,2803,2805,2806],{"id":19,"depth":296,"text":2774},"Q1. In the default event flow model used by the DOM, what happens when a user clicks a deeply nested \u003Cspan> inside several wrapping \u003Cdiv> elements, assuming no listener calls stopPropagation()?",{"id":118,"depth":296,"text":2776},"Q2. By default, element.addEventListener('click', handler) registers the handler for which phase of the event flow?",{"id":199,"depth":296,"text":2778},"Q3. Given nested elements where inner is a direct child of outer, and the following listeners:",{"id":444,"depth":296,"text":2780},"Q4. A \u003Cbutton> has two separate click listeners attached via addEventListener. The first one calls event.stopPropagation(); the second one does nothing special. Both are registered directly on the button (no capture option, no stopImmediatePropagation). When the button is clicked, what happens to the second listener?",{"id":540,"depth":296,"text":2782},"Q5. Calling event.preventDefault() inside a click handler on an \u003Ca href=\"\u002Fpage\"> link does which of the following?",{"id":626,"depth":296,"text":2784},"Q6. A \u003Cul> contains 500 \u003Cli> items that get added and removed dynamically. Which approach is most robust for handling clicks on any \u003Cli>?",{"id":742,"depth":296,"text":2786},"Q7. A delegated click listener on a \u003Cul id=\"list\"> is written as:",{"id":976,"depth":296,"text":2788},"Q8. A \u003Cdiv id=\"outer\"> contains a nested \u003Cbutton>. A single click listener is attached to #outer. When a user clicks the button, inside that listener event.target and event.currentTarget are compared. Which statement is correct?",{"id":1077,"depth":296,"text":1078},{"id":1229,"depth":296,"text":2791},"Q10. What does passing { once: true } as the options argument to addEventListener do?",{"id":1303,"depth":296,"text":1304},{"id":1510,"depth":296,"text":2794},"Q12. Why would you add { passive: true } to a touchstart or wheel event listener that never calls preventDefault()?",{"id":1596,"depth":296,"text":1597},{"id":1736,"depth":296,"text":2797},"Q14. Given child is a descendant of parent:",{"id":1998,"depth":296,"text":2799},"Q15. A team wants to detect when focus leaves a form's container entirely, using event delegation with a single listener on the \u003Cform> element. Which event should they use, and why?",{"id":2095,"depth":296,"text":2801},"Q16. A script runs, in order: btn.onclick = fnA; then btn.onclick = fnB; then btn.addEventListener(\"click\", fnC). When the button is clicked, which handlers run, and in what order?",{"id":2197,"depth":296,"text":2198},{"id":2361,"depth":296,"text":2804},"Q18. A single-page app renders a large \u003Ccanvas> chart and attaches chartCanvas.addEventListener(\"mousemove\", handleHover), where handleHover closes over a large dataset array. When the user navigates away, the component removes the canvas from the DOM via chartCanvas.remove() but never calls removeEventListener. What's the consequence?",{"id":2483,"depth":296,"text":2484},{"id":2551,"depth":296,"text":2807},"Q20. Given child is nested inside parent:","md",{},"\u002Fjs\u002F20-events",{"title":5,"description":217},"js\u002F20-events","lZ6yPmqvskvo2XFn3ltMWA-gOtUU92byhInTwKUHSNw",1787335397335]