JavaScript in the Browser interview revision notes
DOM, events, fetch, storage and other browser APIs you'll commonly face in interviews and real projects. Written for developers preparing for an interview who want to refresh their JavaScript in the Browser fast. Free, no sign-up.
14 topics in these notes
- DOM Basics
- DOM Selectors & Traversal
- Events & Event Delegation
- Forms & Validation
- Fetch API & JSON
- Timers (setTimeout, setInterval)
- localStorage & sessionStorage
- Cookies (basics)
- Location, URL & navigation
- BOM (window, navigator, history, screen)
- Intersection Observer
- requestAnimationFrame
- Web Workers
- CORS & same-origin policy
DOM Basics
Simple real-life example (Understand first — very important for understanding)
- Think of a web page as a tree of boxes: the big box (body) contains smaller boxes (header, main), which contain even smaller ones (paragraphs, buttons).
- Each box is a "node"; JavaScript can find, change, add, or remove these boxes so the page updates without reloading.
- The document is the root of that tree; you start from it to reach any element.
Real-world idea: the page is a tree of elements. The DOM is that tree in memory; JS reads and changes it to update what the user sees.
Technical definition
- DOM (Document Object Model) is a tree representation of the HTML page in memory.
- Each HTML element becomes a
Node/Elementobject (e.g.document.body). - JS can create, read, update and delete DOM nodes to change the page without reload.
- Core entry point:
documentobject (root of the DOM).
Simple practical example
Get the body, create a new paragraph, set its text, and append it to the page so it appears without a full refresh.
Code example
const p = document.createElement('p');
p.textContent = 'Hello, DOM!';
document.body.appendChild(p);Why it matters
Almost all front-end work involves the DOM. Understanding the tree and how to query and update it is essential for dynamic UIs and interviews.
Interview tip
Say: "DOM is the in-memory tree of the page; document is the root. I use it to query elements, change content and attributes, and add or remove nodes."
DOM Selectors & Traversal
Simple real-life example (Understand first — very important for understanding)
- Like finding a person in a building: by name (getElementById), by role (getElementsByClassName), or by a precise description (querySelector).
- Once you have one element, you can move to its parent, children, or siblings—like walking the tree.
- querySelector/querySelectorAll use CSS-style selectors so you can be very specific.
Real-world idea: find one or many elements, then move to nearby nodes. Selectors and traversal are how you navigate the DOM.
Technical definition
getElementById,getElementsByClassName,getElementsByTagName: older APIs; return single element or live HTMLCollection.querySelector/querySelectorAll: CSS selectors; querySelector returns first match, querySelectorAll returns NodeList.- Traversal:
parentElement,children,nextElementSibling,previousElementSibling,closest(selector).
Code example
const card = document.querySelector('.card');
const title = card.querySelector('h2');
const parent = card.parentElement;
const firstChild = card.children[0];Why it matters
Selectors and traversal are used in every script that manipulates the page. Interviewers often ask for the difference between querySelector and getElementById, or how to find the closest parent matching a selector.
Interview tip
"querySelector/querySelectorAll for flexible CSS selectors; getElementById when you have an ID. Use closest() to find an ancestor; children and parentElement for traversal."
Events & Event Delegation
Simple real-life example (Understand first — very important for understanding)
- Like a doorbell: when someone presses it (event), you react (handler). The browser fires events for click, type, submit, scroll, etc.
- Event delegation: instead of attaching a listener to every button, attach one to a parent; when a child is clicked, the event "bubbles" up and the parent can handle it.
- Saves memory and works for dynamically added elements.
Real-world idea: something happens (event), you run a function (handler). Delegation means one listener on a parent handles many children.
Technical definition
addEventListener(type, handler)/removeEventListener; phases: capturing → target → bubbling.- Event delegation: listen on parent, check
event.target(orevent.currentTarget) to decide what was clicked. preventDefault()(e.g. stop form submit / link navigation),stopPropagation()to stop bubbling.
Code example
document.getElementById('list').addEventListener('click', (e) => {
if (e.target.matches('button.delete')) {
e.target.closest('li').remove();
}
});Why it matters
Events are how users interact with the page. Delegation is a common pattern for lists and dynamic content and is a frequent interview topic.
Interview tip
"Use addEventListener; event delegation = one listener on parent, use event.target and matches() to handle specific children. preventDefault for default behavior, stopPropagation to stop bubbling."
Forms & Validation
Simple real-life example (Understand first — very important for understanding)
- Like a paper form: user fills fields; you check that required fields are filled and formats are right (email, number) before sending.
- You can validate on submit (check everything at once) or on blur/input (feedback as they type).
- HTML5 attributes (required, type="email", pattern) plus JS give you both built-in and custom validation.
Real-world idea: collect input and check it before using it. Forms and validation keep data correct and give clear feedback.
Technical definition
- Form elements:
form,input,select,textarea; access viaform.elementsor by name. - Submit: listen to
submitevent, callpreventDefault()to stop native submit, then validate and send (e.g. fetch). - Validation:
required,type,pattern,minLength/maxLength;checkValidity(),setCustomValidity()for custom messages.
Code example
form.addEventListener('submit', (e) => {
e.preventDefault();
if (!form.checkValidity()) return;
const data = new FormData(form);
// send data
});Why it matters
Forms are everywhere (login, search, settings). Knowing how to read values, validate, and prevent default submit is standard front-end and interview material.
Interview tip
"preventDefault on submit; use checkValidity/setCustomValidity or manual checks. FormData for reading form values. Validate on submit and optionally on blur/input."
Fetch API & JSON
Simple real-life example (Understand first — very important for understanding)
- Like sending a letter and waiting for a reply: your page asks another server for data (fetch), gets back a response (often JSON), and then uses it to update the page.
- Fetch is the modern way to do this: you give a URL and options, get a Promise, then read the body as text or JSON.
- JSON is the usual format for APIs: JavaScript objects turned into a string over the wire, then parsed back into objects.
Real-world idea: request data from a server, get a response, parse it (e.g. JSON), and use it. Fetch and JSON are the standard browser way.
Technical definition
fetch(url, options)returns a Promise;response.ok,response.status;response.json()returns Promise of parsed JSON.- Options:
method(GET, POST, etc.),headers(e.g. Content-Type, Authorization),body(string or FormData). - CORS: server must send correct headers to allow the browser to use the response; otherwise the request may be blocked.
Code example
const res = await fetch('/api/users');
if (!res.ok) throw new Error(res.statusText);
const data = await res.json();Why it matters
Fetch and JSON are how front-ends talk to APIs. Interviewers ask about fetch vs XHR, error handling, and CORS.
Interview tip
"fetch returns a Promise; check res.ok and use res.json() for JSON. For POST, set method and Content-Type and pass body. Be aware of CORS."
Timers (setTimeout, setInterval)
Simple real-life example (Understand first — very important for understanding)
- Like an alarm: "run this once after 2 seconds" (setTimeout) or "run this every 2 seconds" (setInterval).
- Use setTimeout for delays (e.g. show a message then hide it) or to defer work; use setInterval for repeated actions (e.g. a clock).
- Clear them with clearTimeout/clearInterval when you no longer need them so they don't keep running.
Real-world idea: run code later (once or repeatedly). Timers are for delays and periodic updates; always clear when done.
Technical definition
setTimeout(callback, ms): run callback once after ms (minimum delay; not guaranteed exact). Returns timer ID.setInterval(callback, ms): run callback every ms. Returns timer ID.clearTimeout(id)/clearInterval(id): cancel the timer. Important to avoid leaks and stray callbacks.
Code example
const id = setTimeout(() => console.log('Later'), 1000);
clearTimeout(id); // cancel if needed
const tick = setInterval(() => updateClock(), 1000);
clearInterval(tick); // stop when doneWhy it matters
Timers are used for debouncing, delays, and periodic UI updates. Knowing when to clear them is part of writing clean front-end code.
Interview tip
"setTimeout for once-after-delay; setInterval for repeat. Always clearTimeout/clearInterval when the component or flow is done to avoid leaks."
localStorage & sessionStorage
Simple real-life example (Understand first — very important for understanding)
- Like a small drawer in the browser: you can put key-value pairs (strings) in it and read them back later, even after closing the tab (localStorage) or only for this tab session (sessionStorage).
- Use for preferences, draft text, or tokens; no server round-trip. Same origin only; limited size (e.g. 5–10 MB).
- Data stays until you remove it (localStorage) or until the tab/session ends (sessionStorage).
Real-world idea: store data in the browser so the page can remember something. localStorage persists; sessionStorage is per tab/session.
Technical definition
localStorage/sessionStorage: same API—setItem(key, value),getItem(key),removeItem(key),clear(). Values are strings.- localStorage: persists across tabs and closes; same origin. sessionStorage: per tab; cleared when tab closes.
- Storage event fires (in other tabs) when localStorage changes; use for syncing or reacting to updates.
Code example
localStorage.setItem('theme', 'dark');
const theme = localStorage.getItem('theme');
localStorage.removeItem('theme');Why it matters
Client-side storage is used for preferences, caching, and offline behavior. Interviewers often ask localStorage vs sessionStorage vs cookies.
Interview tip
"localStorage persists; sessionStorage is per-tab and cleared when tab closes. Both store strings; stringify objects. Same-origin only; size limits apply."
Location, URL & navigation
Simple real-life example (Understand first — very important for understanding)
- Like the address on an envelope: the current page has a full URL (protocol, host, path, query, hash). You can read it or change it (e.g. go to a new page, update the hash).
- location gives you the current URL and lets you assign to it to navigate; URL/URLSearchParams help you parse and build query strings.
- Use when you need to read or change the address bar or handle deep links and query parameters.
Real-world idea: the page has an address; you can read it and change it. Location and URL APIs are for working with that address.
Technical definition
window.location: href, origin, pathname, search, hash; assign to href or use assign()/replace() to navigate.URLconstructor: parse or build URLs;URLSearchParamsfor query string (get, set, append).- hashchange event when the hash changes; useful for single-page app routing or in-page anchors.
Code example
const params = new URLSearchParams(location.search);
const id = params.get('id');
params.set('page', '2');
location.search = params.toString();Why it matters
Reading and updating the URL is central to routing and shareable links. Interviewers may ask about location vs history or how to parse query params.
Interview tip
"location has href, pathname, search, hash; assign to navigate. URLSearchParams for query string. replace() doesn't add history entry; hashchange for hash changes."
BOM (window, navigator, history, screen)
Simple real-life example (Understand first — very important for understanding)
- The browser gives you a "control panel": the window (current tab), info about the device (navigator), the back/forward list (history), and the screen size.
- You use these to adapt the page (e.g. mobile vs desktop), go back/forward, or open new windows.
- They're part of the Browser Object Model—things the browser exposes beyond the document.
Real-world idea: the browser exposes window, device, history, and screen. The BOM is that set of APIs.
Technical definition
window: global object in browser; document, location, history, navigator, setTimeout, etc. are on it.navigator: userAgent, platform, language, geolocation, etc.history: back(), forward(), go(n); pushState/replaceState for SPA routing without full reload.screen: width, height, availWidth, availHeight (useful for layout or analytics).
Code example
history.pushState({ page: 1 }, '', '/page/1');
window.addEventListener('popstate', (e) => { /* handle back/forward */ });Why it matters
BOM APIs are used for routing, device detection, and window management. pushState/popstate is the basis of many SPA routers.
Interview tip
"BOM = window, navigator, history, screen. history.pushState/replaceState + popstate for client-side routing. navigator for device/language; don't rely only on userAgent."
Intersection Observer
Simple real-life example (Understand first — very important for understanding)
- Like a watcher at the edge of the view: "Tell me when this element enters or leaves the visible area (or a certain part of it)."
- Use for lazy-loading images, infinite scroll, or animations that start when something comes into view.
- Much more efficient than constantly checking scroll position in a scroll handler.
Real-world idea: react when an element becomes visible (or leaves). Intersection Observer is the modern, performant way to do that.
Technical definition
IntersectionObserver(callback, options): callback receives entries withisIntersecting,intersectionRatio,target.- Options:
root(default viewport),rootMargin,threshold(e.g. 0.5 = when 50% visible). - observe(target) / unobserve(target) / disconnect(). Use for lazy load, infinite scroll, or view-triggered effects.
Code example
const io = new IntersectionObserver((entries) => {
entries.forEach(e => { if (e.isIntersecting) loadImage(e.target); });
}, { threshold: 0.1 });
document.querySelectorAll('img[data-src]').forEach(img => io.observe(img));Why it matters
Lazy loading and scroll-based UX are common. Intersection Observer is the recommended API and is often discussed in interviews.
Interview tip
"IntersectionObserver detects when element enters/leaves viewport (or root). Use for lazy load and infinite scroll. More efficient than scroll listeners."
requestAnimationFrame
Simple real-life example (Understand first — very important for understanding)
- Like syncing with the TV refresh: instead of "run this every 10 ms" with setInterval, you say "run this before the next paint" so animations are smooth and don't run when the tab is hidden.
- The browser calls your callback before the next repaint; you update positions/state and call requestAnimationFrame again for the next frame.
- Use for animations and smooth updates that should match the display refresh rate.
Real-world idea: run code once per frame, in sync with the display. requestAnimationFrame is for smooth, efficient animations.
Technical definition
requestAnimationFrame(callback): browser calls callback before next repaint; callback receives timestamp. Returns id.- Cancel with
cancelAnimationFrame(id). Loop: call requestAnimationFrame again inside the callback for continuous animation. - Browser throttles when tab is in background; better than setInterval for animations.
Code example
function animate(timestamp) {
// update position
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);Why it matters
Smooth animations and visual updates use requestAnimationFrame. Interviewers may ask RAF vs setInterval for animation.
Interview tip
"requestAnimationFrame runs before next repaint; use for animations. Looping by calling RAF again inside callback. Browser throttles when tab hidden."
Web Workers
Simple real-life example (Understand first — very important for understanding)
- Like giving heavy work to someone else: the main page runs in one thread; a worker runs your script in a separate thread so heavy computation doesn't freeze the UI.
- You send messages to the worker and get messages back; no direct DOM access in the worker.
- Use for big calculations, parsing, or anything that would block the main thread and make the page feel stuck.
Real-world idea: run heavy code in a background thread so the UI stays responsive. Workers communicate by messages.
Technical definition
new Worker(url): runs script in separate thread; no DOM, no window; has postMessage/onmessage.- Main: worker.postMessage(data), worker.onmessage = (e) => e.data. Worker: self.onmessage = (e) => { ...; postMessage(result); }.
- Transferable objects (e.g. ArrayBuffer) for zero-copy transfer. Terminate with worker.terminate().
Code example
// main
const w = new Worker('worker.js');
w.postMessage({ n: 1000000 });
w.onmessage = (e) => console.log(e.data);
// worker.js: onmessage = (e) => { const r = heavy(e.data.n); postMessage(r); }Why it matters
Workers keep the UI responsive during heavy work. Interviewers may ask when to use a worker and how postMessage works.
Interview tip
"Worker runs script in another thread; no DOM. Communicate via postMessage/onmessage. Use for CPU-heavy work so main thread stays responsive."
CORS & same-origin policy
Simple real-life example (Understand first — very important for understanding)
- Same-origin: the browser only lets a page talk freely to the same origin (scheme + host + port). Other origins are "cross-origin."
- CORS: when your page asks another origin for data, the browser sends the request but may block your JS from reading the response unless the server says "this origin is allowed" via headers.
- So the server must send Access-Control-Allow-Origin (and often other CORS headers) for the browser to expose the response to your script.
Real-world idea: the browser restricts cross-origin access. CORS is how servers tell the browser which origins can read the response.
Technical definition
- Same-origin: same protocol, host, port. Cross-origin: different origin; fetches are restricted by default.
- CORS: server responds with
Access-Control-Allow-Origin(and optionally Allow-Methods, Allow-Headers, Allow-Credentials). - Preflight: for non-simple requests the browser sends OPTIONS first; server must allow method/headers. Credentials: use credentials: 'include' and Allow-Credentials: true.
Code example
// Server must send: Access-Control-Allow-Origin: https://mysite.com
// or * for any (no credentials)
fetch('https://api.example.com/data', { credentials: 'include' });Why it matters
CORS and same-origin come up whenever the front-end calls another domain. Understanding preflight and Allow-Origin is essential for APIs and interviews.
Interview tip
"Same-origin = same scheme/host/port. CORS: server sends Access-Control-Allow-Origin (and methods/headers if needed). Preflight for non-simple requests; credentials need Allow-Credentials."
Practise the questions
Read the top 50 JavaScript in the Browser interview questions and answers to test yourself after revising.
More Frontend notes
HTML · CSS · JavaScript · TypeScript · React · Angular · All developer notes