DOM and Browser APIs Quiz: Events, Fetch and CORS Practice
Test your browser JavaScript with 12 questions and three programs on the DOM, event propagation, fetch and CORS, cookies and storage, rendering, XSS and CSRF.
- Course: JavaScript study plan
- Module: The DOM and the browser
- Kind: Checkpoint — cleared at 70%
- Reading time: 24 min
- Runtime: Node 16
Checkpoint — The DOM and the browser is the checkpoint that closes the The DOM and the browser module: a graded quiz and whole-program exercises, passed at 70%.
Instructions
This checkpoint covers the DOM tree and selection, attributes versus properties, textContent versus innerHTML, batching and reflow; event propagation, target/currentTarget, delegation, preventDefault/stopPropagation, custom events; fetch semantics, URL/URLSearchParams, timeouts with AbortController, CORS; Web Storage, cookies and their attributes, the History API, observers and workers; the rendering pipeline, loading path, vitals, and the XSS/CSRF defences.
How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module. The programs model browser mechanisms in Node — a DOM tree, an event dispatcher, a router — because the judge has no browser; the ideas are exactly the browser's.
Before you start, make sure you can answer:
- Attribute versus property for
value; which content API is safe for user data; whygetElementsByClassNamebites when removing. - The three phases; what
closestdoes in a delegated handler; whystopPropagationis usually a smell;passive. - Why a 404 does not reject; how to time out a fetch; what a CORS error means and who fixes it.
- The three cookie flags and what each defends;
pushStateversuspopstate; when to use IndexedDB. - Which CSS properties skip layout;
deferversusasync; the layered XSS defences; the CSRF defence.
The programs are a virtual-DOM differ that emits a minimal patch list, a client-side router with parameterised routes and a history stack, and a stale-while-revalidate fetch cache modelled with timers.
Common questions
Why does getElementsByClassName skip elements when you remove them in a loop?
It returns a live HTMLCollection that updates as the DOM changes. Removing the element at index 0 shifts the next one into index 0 while the loop moves on to index 1, so every other element is skipped. Loop over a static querySelectorAll result, or copy the collection into an array first.
What does closest do in a delegated event handler?
e.target.closest(selector) walks up from the element the event landed on, perhaps an icon inside a button, to the nearest ancestor, or the element itself, that matches the selector. In a delegated listener it finds the item that was actually clicked, and returns null when the click fell between items.
Why is stopPropagation usually a code smell?
Stopping propagation to keep an outer handler from running couples the two handlers invisibly: analytics, a "click outside to close" handler or a delegated listener higher up silently never sees the event. Let events bubble and have the outer handler check e.target instead, for example returning early when the dialog contains it.
Exercises
A virtual-DOM differ
Two lines hold JSON trees: { tag, props, children } where a child is a tree or a string. Write diff(a, b, path, patches) producing, in document order: REPLACE <path> when a text node and an element swap, REPLACE <path> <oldTag> -> <newTag> for different tags (do not descend), TEXT <path> <oldJSON> -> <newJSON>, PROPS <path> <+k=v ~k=v -k …> (added in new-key order, then changed, then removed), and for children by index INSERT <path> <"text" or <tag>> / REMOVE <path>; paths are root, root/0, root/1/0. Print the patches one per line or no changes.
Example: a list whose class and role change, whose first item loses an id, whose second item's text changes, and which gains a fourth item →
PROPS root ~class="list active" +role="list"
PROPS root/0 -id
TEXT root/1/0 "Ink" -> "Blue Ink"
INSERT root/3 <li>A client-side router with a history stack
Lines route <pattern> declare routes with :param segments and a trailing * (captured as rest); compile each to a regex. Keep a history array starting at ["/"] with an index. Commands: push <path?query> (discard the forward stack, append, move) prints pushState <path> -> <match>; replace <path> prints replaceState …; back/forward move the index and print popstate <path> -> <match> (or back: nothing to go back to / forward: nothing ahead); stack prints stack=<JSON> index=<n>. A match is matched <pattern> params=<JSON> query=<JSON of the query string> (first declared route wins) or 404 <pathname>.
Example (excerpt):
pushState /users/42?tab=posts -> matched /users/:id params={"id":"42"} query={"tab":"posts"}
pushState /files/docs/a.pdf -> matched /files/* params={"rest":"docs/a.pdf"} query={}
popstate /users/42/posts/7 -> matched /users/:id/posts/:postId params={"id":"42","postId":"7"} query={}
pushState /nowhere -> 404 /nowhere
A push after going back drops the entries ahead — exactly what the browser does.
A stale-while-revalidate cache
fetchValue(key) (in the starter) takes 10 ms, counts calls and returns <key>#<count>. Implement SwrCache(ttlMs).get(key): on a miss fetch, store with a timestamp and return { status: "miss", value }; when the entry is younger than the TTL return { status: "hit", value }; when it is stale return the stale value immediately as { status: "stale", value } and start one background revalidation that replaces the entry when it completes (a second stale read while it is in flight must not start another). Line 1 is the TTL; commands get <key> print get <key>: <status> <value> fetches=<count> and wait <ms> prints (waited <ms> ms).
Example: TTL 40, then get a, get a, wait 60, get a, get a, wait 20, get a, get b →
get a: miss a#1 fetches=1
get a: hit a#1 fetches=1
(waited 60 ms)
get a: stale a#1 fetches=2
get a: stale a#1 fetches=2
(waited 20 ms)
get a: hit a#2 fetches=2
get b: miss b#3 fetches=3
The stale reads answered instantly with the old value while one refresh ran; the next read after it landed was fresh.
In this module: The DOM and the browser
- The DOM — the tree behind the page, and how to change it safely
- Events — propagation, delegation and the event object
- fetch, URLs, CORS and talking to servers
- Storage, cookies, history and the browser APIs worth knowing by name
- Rendering performance and front-end security — the two things a page must not get wrong
- Checkpoint — The DOM and the browser (this lesson)
← Rendering performance and front-end security — the two things a page must not get wrong · What TypeScript adds — erased types, inference, and any versus unknown versus never →