Skip to content

Frontend Development Mock Interview: 20 Questions in 50 Minutes

Four rounds that copy a real interview. Answer aloud, then check the model answers.

Mock interview format

  1. Warm-up · 5 minutes — 4 questions
  2. Technical · 20 minutes — 7 questions
  3. Scenario · 15 minutes — 5 questions
  4. HR & behavioural · 10 minutes — 4 questions

Tip: record yourself and listen back. Most people talk too fast and skip the key idea.

Mock progressStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

What is the difference between unit, integration and end-to-end tests?

Warm-upFrontend TestingEasy
Save to ▾
Show answer
A unit test checks a single function or module in isolation, such as a price formatter. An integration test checks several pieces working together, like a form component with validation and an API call mocked at the network level. An end-to-end test drives a real browser through a complete user flow, such as signup to dashboard, against a running app. They trade speed for realism in that order.
02

How do browser permission APIs like Geolocation and Notifications work?

Warm-upBrowser APIsEasy
Save to ▾
Show answer
Powerful features require user consent, a secure HTTPS context and usually a user gesture. Calling navigator.geolocation.getCurrentPosition or Notification.requestPermission shows a browser prompt; if the user denies it, you cannot ask again easily. navigator.permissions.query lets you check the current state first. Good UX explains why you need the permission before triggering the prompt, for example asking for location only when the user taps 'Find nearest centre'.
03

When should you use Map and Set instead of plain objects and arrays?

Save to ▾
Show answer
Map allows keys of any type, keeps insertion order, has a size property and performs well with frequent additions and deletions, so it suits caches and lookups by object. Set stores unique values with fast has() checks, ideal for tracking selected ids. Plain objects are better for fixed-shape records and JSON. Arrays are better when order and index access matter and duplicates are allowed.
04

What are code splitting and lazy loading?

Warm-upWeb PerformanceEasy
Save to ▾
Show answer
Code splitting breaks a large JavaScript bundle into smaller chunks so the browser downloads only what the current page needs. Lazy loading defers loading code or assets until they are required, using dynamic import() for components like a chart or a rich text editor. Route-based splitting is the most common starting point. It reduces initial download and parse time, which improves LCP and INP on slower devices.
05

Detect offline status and retry queued requests when the connection returns.

TechnicalBrowser APIsMedium
Save to ▾
Show answer
Listen for online and offline events and keep a small queue: const queue = []; async function send(req) { if (!navigator.onLine) { queue.push(req); showBanner('You are offline'); return; } await fetch(req.url, req.options); } window.addEventListener('online', async () => { hideBanner(); while (queue.length) await send(queue.shift()); }); window.addEventListener('offline', () => showBanner('You are offline')); navigator.onLine can report true on captive networks, so treat failed fetches as offline too. Persist the queue in IndexedDB for reliability.
06

Write a minimal observable store in plain JavaScript.

TechnicalFrontend ArchitectureMedium
Save to ▾
Show answer
A store holds state and notifies subscribers: function createStore(initial) { let state = initial; const listeners = new Set(); return { get: () => state, set(update) { state = { ...state, ...update }; listeners.forEach(fn => fn(state)); }, subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); } }; } const cart = createStore({ items: 0 }); const stop = cart.subscribe(s => (badge.textContent = s.items)); cart.set({ items: 2 }); The returned unsubscribe function prevents memory leaks.
07

Create a simple custom element with Shadow DOM.

TechnicalBrowser APIsMedium
Save to ▾
Show answer
Extend HTMLElement and register a tag name containing a hyphen: class RatingStars extends HTMLElement { connectedCallback() { const value = Number(this.getAttribute('value') || 0); const root = this.attachShadow({ mode: 'open' }); root.innerHTML = `<style>span { color: var(--star-color, orange); }</style> <span role='img' aria-label='${value} out of 5'>${'*'.repeat(value)}</span>`; } } customElements.define('rating-stars', RatingStars); // usage: <rating-stars value='4'></rating-stars> The custom property lets the page theme it despite Shadow DOM isolation.
08

Run linting and formatting automatically before each commit.

Save to ▾
Show answer
Use Husky with lint-staged: npm i -D husky lint-staged npx husky init echo 'npx lint-staged' > .husky/pre-commit // package.json "lint-staged": { "*.{ts,tsx,js}": ["eslint --fix", "prettier --write"], "*.{css,md,json}": "prettier --write" } Only staged files are checked, so commits stay fast. CI should still run the full lint because hooks can be skipped locally.
09

Write a React custom hook that fetches data and cancels on unmount.

TechnicalFrontend ArchitectureMedium
Save to ▾
Show answer
Use AbortController inside useEffect: import { useEffect, useState } from 'react'; export function useFetch(url) { const [state, setState] = useState({ data: null, error: null, loading: true }); useEffect(() => { const controller = new AbortController(); setState(s => ({ ...s, loading: true })); fetch(url, { signal: controller.signal }) .then(r => (r.ok ? r.json() : Promise.reject(new Error(r.status)))) .then(data => setState({ data, error: null, loading: false })) .catch(err => { if (err.name !== 'AbortError') setState({ data: null, error: err, loading: false }); }); return () => controller.abort(); }, [url]); return state; } In production apps, TanStack Query adds caching and retries.
10

What is the same-origin policy and how does postMessage work around it?

TechnicalBrowser APIsMedium
Save to ▾
Show answer
An origin is the combination of scheme, host and port. The same-origin policy stops scripts from reading data or DOM of another origin, such as an embedded iframe from a payment provider. window.postMessage lets two windows or iframes exchange messages safely across origins. The receiver must check event.origin against an allow-list, and the sender should specify the exact target origin instead of '*'.
11

What does the :has() selector allow you to do?

Save to ▾
Show answer
:has() is often called the parent selector because it styles an element based on what it contains or what follows it. For example, .card:has(img) can change padding for cards with images, and form:has(input:invalid) can highlight a form with errors. It removes many cases where JavaScript was used only to toggle classes. It is supported in all modern browsers.
12

npm audit reports a critical vulnerability in a dependency. What do you do?

Save to ▾
Show answer
I would check whether the vulnerable package is actually used in the production bundle or only in build tooling, and whether the vulnerable code path is reachable. Then I would update to a patched version, using npm update or overrides for transitive dependencies. If no fix exists, I would look for an alternative package or mitigate. Automated tools like Dependabot or Renovate keep dependencies current.
13

In a single-page app, the back button takes users out of the site instead of to the previous filter. Why?

ScenarioBrowser APIsMedium
Save to ▾
Show answer
The app changes the view without adding history entries, so the browser has nothing to go back to within the site. Each meaningful navigation, like changing a category or opening a product, should call pushState or the router's navigate function, while minor changes such as typing in search can use replaceState. The app must also listen to popstate and restore the view and scroll position from the URL.
14

TypeScript types say a field exists, but the app crashes because the API did not send it. How do you prevent this?

ScenarioTypeScriptHard
Save to ▾
Show answer
TypeScript only checks at compile time; it cannot guarantee what a server returns at runtime. I would validate responses at the boundary with a schema library like Zod or Valibot, deriving TypeScript types from the schema so they never drift. Invalid data then fails clearly with a logged error and a fallback UI. Generating types from OpenAPI specs also keeps frontend and backend contracts aligned.
15

Which rendering strategy would you choose for a large e-commerce site?

Save to ▾
Show answer
I would mix strategies by page type. Category and product pages need SEO and fast LCP, so I would use static generation with incremental revalidation or server rendering with CDN caching. Cart, checkout and account pages are personalised, so server rendering without shared caching or client rendering works. Prices and stock can be fetched fresh on the client. Frameworks like Next.js, Nuxt and Astro support this per-route choice.
16

State is passed through many component layers and global state has become chaotic. How do you restructure it?

ScenarioFrontend ArchitectureMedium
Save to ▾
Show answer
I would first classify state: server data moves to a data-fetching cache like TanStack Query, URL-worthy state such as filters moves to query parameters, and truly local state moves back into components. What remains global, like user session and theme, goes into a small, well-defined store or context split by concern. Composition patterns, passing components as children, also remove much prop drilling.
17

How would you learn TypeScript quickly if your new project required it?

HR & behaviouralTypeScriptEasy
Save to ▾
Show answer
Situation: I joined an internship where the codebase was fully TypeScript, which I had never used. Task: I needed to contribute within the first week. Action: I read the official handbook basics, studied existing types in the project, and converted small JavaScript exercises into TypeScript each evening. Result: I submitted my first typed component on day five and became comfortable with generics within a month.
18

How do you handle a designer who expects pixel-perfect matching on every device?

Save to ▾
Show answer
Situation: a designer flagged small spacing differences between Figma and my build on several phones. Task: I needed to address concerns while keeping the layout fluid. Action: I fixed genuine mistakes immediately, then showed how fixed pixel values would break on other screens and proposed shared spacing tokens. Result: we agreed on tokens and breakpoints, and future handoffs had far fewer revision rounds.
19

Tell me about a time you automated a repetitive task.

HR & behaviouralBuild Tools and ToolingEasy
Save to ▾
Show answer
Situation: in my internship, we resized and compressed product images manually before every upload. Task: I wanted to save the team time. Action: I wrote a small Node script using Sharp that converted images to WebP in three sizes and added it as an npm script. Result: a task that took an hour per batch became a one-minute command, and image sizes dropped by more than half.
20

How do you handle a situation where a bug you wrote affected users?

HR & behaviouralFrontend TestingEasy
Save to ▾
Show answer
Situation: a form validation change I made blocked some users from signing up with valid numbers. Task: I needed to fix it and be transparent. Action: I informed my lead immediately, rolled back the change, found that my regex rejected numbers with a +91 prefix, fixed it, and added tests for different formats. Result: signups recovered within an hour, and I now test with real-world data samples.

Frequently asked questions

How do I use this mock interview?

Set a 50-minute timer, answer every question aloud (or ask a friend to read them), and open answers only after each round. Note every question where your answer missed the key idea.

How often should I take a mock?

Once a week while preparing and once two or three days before a real interview. The question order is fixed, so for fresh practice use the company and experience pages too.