RSRobince Studio

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

  1. DOM Basics
  2. DOM Selectors & Traversal
  3. Events & Event Delegation
  4. Forms & Validation
  5. Fetch API & JSON
  6. Timers (setTimeout, setInterval)
  7. localStorage & sessionStorage
  8. Cookies (basics)
  9. Location, URL & navigation
  10. BOM (window, navigator, history, screen)
  11. Intersection Observer
  12. requestAnimationFrame
  13. Web Workers
  14. 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/Element object (e.g. document.body).
  • JS can create, read, update and delete DOM nodes to change the page without reload.
  • Core entry point: document object (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 (or event.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 via form.elements or by name.
  • Submit: listen to submit event, call preventDefault() 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 done

Why 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."

Cookies (basics)

Simple real-life example (Understand first — very important for understanding)

  • Like a small slip the server asks the browser to keep: the server sends "Set-Cookie"; the browser sends that cookie back with every request to that domain.
  • Use for session IDs, preferences, or tracking; they're sent automatically so the server can "recognize" the user.
  • They have size limits, expiry, and security options (HttpOnly, Secure, SameSite).

Real-world idea: the server gives the browser a small piece of data to send back on future requests. Cookies are for identity and preferences.

Technical definition

  • Cookies: set by server via Set-Cookie header or in JS via document.cookie (read/write string).
  • Attributes: expires/max-age, path, domain, Secure (HTTPS only), HttpOnly (no JS access), SameSite (CSRF protection).
  • document.cookie returns all cookies for the page as one string; to set: document.cookie = 'name=value; path=/; max-age=3600'.

Code example

document.cookie = 'theme=dark; path=/; max-age=86400; SameSite=Lax';

Why it matters

Cookies are still used for sessions and auth. Understanding expiry, HttpOnly, and SameSite is important for security and interviews.

Interview tip

"Cookies are set by Set-Cookie or document.cookie; sent with requests. Use HttpOnly for tokens, Secure on HTTPS, SameSite for CSRF. Prefer localStorage for client-only data."

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.
  • URL constructor: parse or build URLs; URLSearchParams for 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 with isIntersecting, 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."

More Frontend notes

HTML · CSS · JavaScript · TypeScript · React · Angular · All developer notes