Frontend Developer Interview Questions and How to Answer Them (50+)
You spent weeks building side projects, reading docs, and watching tutorials. Now there's a technical interview on your calendar and you need to know if you're ready.
This guide covers the 50+ most common frontend interview questions — from HTML fundamentals to React internals to system design — with detailed answers and real code you can study and adapt. No padding, no theory without practice.
Work through each section. If you can answer confidently without looking, you're ready. If you have to read the answer first, that's the gap to close before the interview.
Section 1: HTML Fundamentals
1. What is the difference between `<div>` and `<span>`?
Use It tells the browser which version of HTML the document uses. Without it, browsers enter "quirks mode" — a legacy compatibility mode that renders CSS and HTML differently across browsers, causing layout inconsistencies. Semantic HTML uses elements that describe their meaning in human-readable and machine-readable ways. It matters for three reasons: accessibility (screen readers use landmarks), SEO (search engines weight content in semantic containers differently), and maintainability (code is easier to understand). All three load an external JavaScript file. The difference is when the script executes relative to HTML parsing. For most application scripts: use It provides a text alternative when the image cannot be displayed, and is read aloud by screen readers for visually impaired users. It also appears when the image fails to load. Empty All three store data in the browser, but they differ in scope, expiration, and how they're sent to the server. | | localStorage | sessionStorage | Cookies | |---|---|---|---| | Expires | Never (until cleared) | Tab close | Set by server/JS | | Sent to server | No | No | Yes (on every request) | | Capacity | ~5MB | ~5MB | ~4KB | | Accessible from JS | Yes | Yes | Yes (if no HttpOnly) | Use Every HTML element is a box with four layers: content, padding, border, and margin. By default ( Reset to Specificity determines which CSS rule wins when multiple rules target the same element. It's calculated as a score across four categories: inline styles, IDs, classes/attributes/pseudo-classes, and elements/pseudo-elements. | Selector | Score | |---|---| | | | | The rule with the highest specificity wins. Equal specificity: last rule in source order wins. The most common trap: Flexbox is a one-dimensional layout system. You set Grid is a two-dimensional layout system — rows and columns simultaneously. Flexbox handles one dimension at a time. Use Grid for page-level layout (two-dimensional). Use Flexbox for component-level layout. They compose well. Best practice: use A pseudo-class selects an element based on its state ( Unlike SASS variables (compile-time), CSS custom properties are live — updatable with JavaScript, scopeable, and cascade like any other property. Rule of thumb: use A closure is a function that retains access to its outer scope even after the outer function has returned. Classic closure trap in loops: JavaScript is single-threaded. The event loop lets it handle async operations without blocking. Why? Synchronous code runs first (1, 4). Microtasks (Promises) run before the next macrotask (3). Macrotasks (setTimeout) run last (2). Use A Promise represents an async operation with three states: pending, fulfilled, rejected. A higher-order function takes a function as argument or returns one. Every object has a Generators pause execution and yield multiple values over time. Uses: pagination, infinite scrolls, state machines, async flow control. Events travel in two phases: capturing (html → target) then bubbling (target → html). Add one listener to a parent instead of N listeners on children. Batch DOM operations off-document, then insert once — avoiding multiple reflows. HTML → DOM, CSS → CSSOM → Render Tree → Layout → Paint → Composite. Avoid layout thrashing — batch reads then writes: Web Workers run JS in a background thread without blocking the UI. Uses: image processing, large data parsing, encryption, complex sorting. The Virtual DOM is a lightweight JS representation of the real DOM. React diffs the new and previous Virtual DOM trees (reconciliation), then applies only the minimum changes to the real DOM. This avoids expensive full re-renders. Two rules: only call hooks at the top level; only call them from React function components or custom hooks. Use for components that render often with same props. Don't apply blindly — profile first. Use for globally stable values (theme, locale, auth). Avoid for high-frequency updates. Controlled: React state drives the input value. Uncontrolled: the DOM manages its own state, read via refs. Use Both work for objects. ARIA attributes convey semantics to assistive technologies when native HTML isn't enough. The first rule of ARIA: don't use it if native HTML already provides the semantics. CORS controls which origins can make requests to your server. Enforced by browsers. The browser blocks the response if headers don't match. CORS is a browser protection, not a server one. XSS injects malicious scripts into your page to steal cookies, redirect, or hijack sessions. Also: use HttpOnly cookies, implement CSP headers. Authentication: who are you? (verify credentials, issue token) Authorization: what can you do? (check permissions on a resource) Webpack: bundles everything upfront in dev. Slower for large apps but mature. Vite: serves native ESM in dev — no bundling. Only changed modules are hot-replaced. Uses Rollup for production. Dramatically faster for large apps. For new projects: Vite. For legacy: Webpack. Tree shaking eliminates dead code — exports imported but never used. Requirements: ES modules, no side effects in unused code, production build. Each lazy-loaded route becomes a separate chunk downloaded on demand. Spy: wraps the original, observes calls without changing behavior. Mock: replaces the function entirely with a controlled substitute. Key decisions: React Query for server state, Zustand for client state, React Hook Form + Zod for forms, lazy routes, error boundaries per feature. Work through each question out loud — not just reading the answer. The interview is verbal. Prioritize based on the job: The best candidates explain the "why" behind their answer and mention trade-offs. When asked about debounce, don't just show the implementation — explain why: "to avoid API calls on every keystroke, reducing server load and preventing race conditions where a slow earlier response overwrites a newer one." That's what separates the hire from the no-hire. The most common frontend interview questions cover JavaScript fundamentals (closures, the event loop, promises, 'this'), CSS layout (flexbox, grid, box model, specificity), React concepts (hooks, virtual DOM, controlled components), and performance topics (debounce/throttle, critical rendering path, code splitting). These appear in virtually every frontend interview regardless of company or seniority level. Senior frontend interviews go beyond syntax. Expect system design questions (how to architect a large app, how to handle state at scale), performance deep-dives (profiling, bundle optimization, virtual lists), and questions about trade-offs between technologies. Study React internals, TypeScript generics, web security (XSS, CORS), accessibility patterns, and testing strategies. Practice explaining your decisions out loud, not just writing code. Yes, for most mid-level and senior roles TypeScript is expected. Know the difference between interface and type, understand generics, utility types (Partial, Required, Pick, Omit), and how to type function signatures and API responses. You don't need to know every advanced feature, but you should be able to write type-safe component props and API calls without help. The most common: explain the rules of hooks and why they exist, the difference between useState and useReducer, when to use useEffect vs useLayoutEffect, how to use useRef for DOM access vs mutable values, and how useMemo/useCallback optimize renders. Beyond individual hooks, expect to explain how the dependency array works and common bugs (stale closures, missing dependencies). A closure is a function that retains access to variables from its outer scope even after the outer function has finished executing. This happens because functions in JavaScript capture a reference to their surrounding scope, not a copy. Closures are used for private state, factory functions, debounce/throttle implementations, and memoization. The classic interview example is a counter factory that returns increment/decrement functions with private count state. Flexbox is one-dimensional — it arranges items along a single axis (row or column) and is ideal for component-level layouts like navigation bars, button groups, and card content. CSS Grid is two-dimensional — it handles rows and columns simultaneously and is ideal for page-level layouts. They compose well: use Grid for the overall page structure and Flexbox inside each grid cell for its internal layout. The main prevention strategies are: use textContent instead of innerHTML when inserting user-provided data into the DOM, sanitize any HTML you must render with a library like DOMPurify, implement a Content Security Policy header to restrict script sources, set cookies as HttpOnly so JavaScript cannot access them, and never use dangerouslySetInnerHTML in React unless you've sanitized the content. React's JSX auto-escapes interpolated values, which provides baseline XSS protection. Know semantic HTML and why it matters for screen readers and SEO. Understand ARIA attributes — role, aria-label, aria-hidden, aria-live, aria-expanded — and when to use them vs native HTML elements (native first, ARIA only when HTML falls short). Know how to implement keyboard navigation (focus management, arrow key navigation, Escape to close). Understand color contrast requirements and focus indicators. Be able to explain how to make a custom dropdown or modal accessible. How to Answer Conflict-With-a-Coworker Interview Questions Learn how to answer conflict-with-a-coworker interview questions with real examples and proven techniques. Stand out in tech and remote job interviews. How to Answer 'Why Do You Want to Work Here' in Interviews Discover expert strategies for answering 'why do you want to work here,' tailored for remote tech roles and dollar opportunities. Real, practical interview tips. Full-Stack Developer Interview Questions: How to Answer Like a Pro (45+) Comprehensive full-stack developer interview guide with 46 numbered questions covering JavaScript/TypeScript, React, CSS, REST APIs, databases, Node.js, system design, security, testing, DevOps, and advanced architecture topics. Each answer includes working code examples and production-level context. Backend Developer Interview Questions: Real Answers and Strategies (50+) A comprehensive guide covering 50+ backend developer interview questions with detailed answers, real code examples in Python, JavaScript, Java, SQL, and Go, and strategic advice for each question type — from data structures and databases to system design, concurrency, security, and architecture. Paste your job link: we research who's interviewing you and rehearse you live. Have an interview coming up? Install the live copilot → is an inline element — it only takes up as much space as its content and does not break the flow.<!-- div stacks vertically -->
<div style="background: lightblue;">Block element</div>
<div style="background: lightgreen;">Another block</div>
<!-- span sits inline -->
<p>This word is <span style="color: red;">highlighted</span> inline.</p> to style or target a portion of text within a line.2. What does `<!DOCTYPE html>` do and why does it matter?
is the HTML5 doctype. It must be the very first line of your HTML file, before even the tag.<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>My Page</title>
</head>
<body>...</body>
</html>3. What is semantic HTML and why does it matter?
, , , , , and tell browsers, screen readers, and search engines what role each piece of content plays.<!-- Non-semantic -->
<div class="header">
<div class="nav">...</div>
</div>
<!-- Semantic -->
<header>
<nav>...</nav>
</header>4. What is the difference between `<script>`, `<script async>`, and `<script defer>`?
: parsing stops, script downloads and executes immediately, then parsing resumes. Blocks rendering.: script downloads in parallel, executes as soon as it's ready — even if parsing isn't done. Order not guaranteed.: script downloads in parallel, executes after parsing is complete, in document order.<!-- Blocks HTML parsing — avoid for non-critical scripts -->
<script src="app.js"></script>
<!-- Good for independent third-party scripts (analytics, ads) -->
<script async src="analytics.js"></script>
<!-- Best for your own scripts that depend on the DOM -->
<script defer src="main.js"></script>defer. For independent third-party scripts where order doesn't matter: use async.5. What is the purpose of the `alt` attribute on images?
<!-- Good: descriptive -->
<img src="team-photo.jpg" alt="Engineering team at company offsite in Buenos Aires" />
<!-- Decorative image: empty alt so screen readers skip it -->
<img src="decorative-divider.svg" alt="" />
<!-- Bad: missing alt entirely -->
<img src="product.jpg" />alt="" is intentional for decorative images. Missing alt entirely is an accessibility failure.6. What is the difference between `localStorage`, `sessionStorage`, and cookies?
// localStorage — persists across tabs and restarts
localStorage.setItem('theme', 'dark');
const theme = localStorage.getItem('theme');
localStorage.removeItem('theme');
// sessionStorage — tab-scoped
sessionStorage.setItem('draft', JSON.stringify({ title: 'My post' }));
// Cookies — sent with every HTTP request to the domain
document.cookie = 'session=abc123; path=/; Secure; SameSite=Strict';localStorage for user preferences. Use sessionStorage for temporary state within a tab. Use cookies for auth tokens that the server needs to read.Section 2: CSS
7. Explain the CSS box model.
box-sizing: content-box), width and height only apply to the content. Padding and border are added on top. This leads to math surprises./* Default: width = content only */
.box {
width: 200px;
padding: 20px;
border: 2px solid black;
/* Total rendered width: 200 + 40 + 4 = 244px */
}
/* border-box: width includes padding + border */
* {
box-sizing: border-box;
}
.box {
width: 200px;
padding: 20px;
border: 2px solid black;
/* Total rendered width: 200px — no surprises */
}border-box globally on every project. It's what everyone expects.8. What is CSS specificity and how is it calculated?
style="" (inline) | 1,0,0,0 |#id | 0,1,0,0 |.class, [attr], :hover | 0,0,1,0 |div, ::before | 0,0,0,1 |p { color: black; } /* 0,0,0,1 */
.intro { color: blue; } /* 0,0,1,0 */
#hero { color: red; } /* 0,1,0,0 */
p.intro { color: green; } /* 0,0,1,1 */!important overrides everything but should be a last resort.9. What is the difference between `position: relative`, `absolute`, `fixed`, and `sticky`?
/* relative: offset from its normal position, still occupies space */
.box { position: relative; top: 10px; left: 20px; }
/* absolute: removed from flow, positioned relative to nearest positioned ancestor */
.tooltip { position: absolute; top: 0; right: 0; }
/* fixed: removed from flow, positioned relative to viewport */
.navbar { position: fixed; top: 0; width: 100%; }
/* sticky: relative until scroll threshold, then fixed */
.table-header { position: sticky; top: 0; }position: absolute looks for the nearest ancestor with position set to anything other than static. If none exists, it positions relative to .10. How does Flexbox work? Walk me through the main properties.
display: flex on a container and it controls how its direct children (flex items) are arranged..container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 16px;
flex-wrap: wrap;
}
.item {
flex: 1;
flex-grow: 1;
flex-shrink: 0;
flex-basis: 200px;
align-self: flex-end;
}
/* Centering anything */
.centered {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}11. What is CSS Grid and when would you use it over Flexbox?
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
.hero { grid-column: 1 / -1; }
.layout {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 250px 1fr;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }12. What is the difference between `em`, `rem`, `px`, `vw`, and `%`?
.box { font-size: 16px; } /* px — absolute */
.child { font-size: 1.5em; } /* em — relative to element's font-size */
.any { font-size: 1.5rem; } /* rem — relative to root, no compounding */
.hero { height: 100vh; width: 100vw; } /* viewport units */
.child { width: 50%; } /* % — relative to parent */rem for font sizes and spacing, px only for borders and fine details, % and vw/vh for responsive layout.13. What is a CSS pseudo-class vs a pseudo-element?
:hover, :focus, :nth-child()). A pseudo-element creates a virtual element (::before, ::after, ::first-line).button:hover { background: #0056b3; }
input:focus { outline: 2px solid blue; }
li:nth-child(2n) { background: #f5f5f5; }
.card::before {
content: "";
display: block;
width: 4px;
background: blue;
position: absolute;
left: 0;
}14. How do CSS custom properties (variables) work?
:root {
--color-primary: #3b82f6;
--spacing-md: 16px;
}
.button {
background: var(--color-primary);
padding: var(--spacing-md);
}
.button.danger { --color-primary: #ef4444; }
@media (prefers-color-scheme: dark) {
:root { --color-text: #f9fafb; }
}Section 3: JavaScript Core
15. What is the difference between `var`, `let`, and `const`?
// var: function-scoped, hoisted, can be re-declared
function example() {
console.log(x); // undefined (hoisted)
var x = 5;
if (true) { var x = 10; } // same variable
console.log(x); // 10
}
// let: block-scoped, not initialized until declaration
{ let y = 5; }
// console.log(y); // ReferenceError
// const: block-scoped, cannot be reassigned
const z = 5;
const user = { name: 'Ana' };
user.name = 'Carlos'; // ok — mutation allowed
// user = {}; // TypeError — reassignment failsconst by default, let when you need to reassign, never var.16. Explain closures with a practical example.
function makeCounter(start = 0) {
let count = start;
return {
increment() { count += 1; },
decrement() { count -= 1; },
value() { return count; }
};
}
const counter = makeCounter(10);
counter.increment();
counter.increment();
console.log(counter.value()); // 12// Bug: all callbacks close over the same `i`
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 3, 3, 3
}
// Fix: use let (block scope creates new binding per iteration)
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 0, 1, 2
}17. What is the event loop and how does JavaScript handle async code?
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// Output: 1, 4, 3, 218. What is the difference between `==` and `===`?
== performs type coercion before comparing. === compares both value and type without coercion.0 == '0' // true (coercion)
0 === '0' // false
null == undefined // true (special case)
NaN === NaN // false — use Number.isNaN(NaN) instead=== in all cases.19. What are Promises and how do they work?
const fetchUser = (id) =>
new Promise((resolve, reject) => {
if (id > 0) resolve({ id, name: 'Ana Garcia' });
else reject(new Error('Invalid ID'));
});
// async/await
async function getUser(id) {
try {
const user = await fetchUser(id);
console.log(user.name);
} catch (err) {
console.error(err.message);
}
}
// Parallel
const [user, posts] = await Promise.all([fetchUser(1), fetchPosts(1)]);20. Explain `this` in JavaScript.
this refers to the executing context. Its value depends on how the function is called.const obj = { name: 'Ana', greet() { console.log(this.name); } };
obj.greet(); // 'Ana'
const greet = obj.greet;
greet(); // undefined — lost context
// Arrow functions inherit this from surrounding scope
const obj2 = { name: 'Carlos', greet: () => console.log(this.name) };
obj2.greet(); // undefined
// Explicit binding
say.call({ name: 'Ana' }, 'Hello');
const bound = say.bind({ name: 'Ana' });
bound('Hey');21. What are higher-order functions?
const products = [
{ name: 'Laptop', price: 1200, inStock: true },
{ name: 'Mouse', price: 25, inStock: false },
{ name: 'Keyboard', price: 80, inStock: true },
];
const names = products.map(p => p.name);
const available = products.filter(p => p.inStock);
const total = products.filter(p => p.inStock).reduce((sum, p) => sum + p.price, 0);
const cheap = products.find(p => p.price < 100);
const allAffordable = products.every(p => p.price < 500);22. What is destructuring and the spread/rest operator?
const [first, second, ...rest] = [1, 2, 3, 4, 5];
const { name, age, role = 'user' } = { name: 'Ana', age: 28 };
const { name: userName } = { name: 'Carlos' };
// Spread
const arr2 = [...arr1, 4, 5];
const obj2 = { ...obj1, b: 2 };
// Rest
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}23. What is the difference between `null`, `undefined`, and `NaN`?
let x; // undefined — declared but not assigned
let user = null; // null — intentional absence
parseInt('hello') // NaN — invalid math
typeof undefined // 'undefined'
typeof null // 'object' (historical bug)
typeof NaN // 'number' (counterintuitive)
Number.isNaN(NaN) // true — correct check24. How does prototypal inheritance work in JavaScript?
[[Prototype]] link. When you access a property that doesn't exist, JavaScript walks up the chain.class Animal {
constructor(name) { this.name = name; }
speak() { return `${this.name} makes a noise.`; }
}
class Dog extends Animal {
bark() { return `${this.name} barks.`; }
}
const d = new Dog('Rex');
d.speak(); // inherited
d instanceof Animal; // true25. What are generators and when would you use them?
function* range(start, end, step = 1) {
for (let i = start; i < end; i += step) yield i;
}
const nums = [...range(0, 10, 2)]; // [0, 2, 4, 6, 8]
function* fibonacci() {
let [a, b] = [0, 1];
while (true) { yield a; [a, b] = [b, a + b]; }
}Section 4: Browser and DOM
26. What is the difference between event bubbling and capturing?
document.querySelector('#parent').addEventListener('click', () => console.log('parent'));
document.querySelector('#child').addEventListener('click', (e) => {
console.log('child');
e.stopPropagation(); // prevent parent from firing
});27. What is event delegation and why is it useful?
document.querySelector('#list').addEventListener('click', (e) => {
const item = e.target.closest('.item');
if (!item) return;
handleClick(item);
});
// Works for dynamically added elements too28. What is the difference between `getElementById`, `querySelector`, and `querySelectorAll`?
const el = document.getElementById('app'); // fastest, no '#'
const btn = document.querySelector('#app .btn'); // CSS selector, first match
const items = document.querySelectorAll('.item'); // CSS selector, static NodeList
items.forEach(item => item.classList.toggle('active'));29. What is a DocumentFragment and why would you use it?
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
document.getElementById('list').appendChild(fragment); // single reflow30. What is the difference between `innerHTML`, `textContent`, and `innerText`?
el.innerHTML = '<strong>Hello</strong>'; // parses HTML — XSS risk with user input
el.textContent = '<strong>Hello</strong>'; // literal text, safe
el.innerText; // visible text only, triggers reflow
el.textContent = userInput; // safe way to insert user contentSection 5: Performance
31. What is the critical rendering path and how do you optimize it?
<script defer src="app.js"></script>
<link rel="preload" as="font" href="font.woff2" crossorigin>
<img src="hero.webp" loading="lazy" width="800" height="600" alt="...">const widths = elements.map(el => el.offsetWidth); // all reads
elements.forEach((el, i) => { el.style.width = widths[i] + 10 + 'px'; }); // all writes32. What is debouncing and throttling? Implement both.
function debounce(fn, delay) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
}
function throttle(fn, limit) {
let lastCall = 0;
return function (...args) {
const now = Date.now();
if (now - lastCall >= limit) { lastCall = now; fn.apply(this, args); }
};
}
const search = debounce(query => fetch(`/search?q=${query}`), 300);
const onScroll = throttle(() => console.log(window.scrollY), 100);33. What are Web Workers and when would you use them?
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ data: largeArray });
worker.onmessage = (e) => console.log('Result:', e.data.result);
// worker.js
self.onmessage = (e) => {
const result = e.data.data.reduce((sum, x) => sum + x, 0);
self.postMessage({ result });
};Section 6: React
34. What is the Virtual DOM and how does React use it?
35. What are React hooks and what are the rules for using them?
function SearchResults({ query }) {
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!query) return;
setLoading(true);
fetch(`/api/search?q=${query}`)
.then(r => r.json())
.then(data => { setResults(data); setLoading(false); });
return () => {}; // cleanup
}, [query]);
const sorted = useMemo(
() => [...results].sort((a, b) => b.score - a.score),
[results]
);
const handleClick = useCallback((id) => {
setResults(prev => prev.filter(r => r.id !== id));
}, []);
return loading ? <Spinner /> : <List items={sorted} onRemove={handleClick} />;
}36. What is the difference between `useEffect` and `useLayoutEffect`?
useEffect: runs after the browser paints. Won't block visual updates. Default choice.useLayoutEffect: runs after DOM mutations but before paint. Use when you need to measure/mutate DOM without a visual flash.37. What is React.memo and when should you use it?
React.memo skips re-rendering a component if its props haven't changed.const UserCard = React.memo(function UserCard({ name, avatar }) {
return <div><img src={avatar} />{name}</div>;
});38. What is the Context API?
const ThemeContext = React.createContext('light');
function App() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Layout />
</ThemeContext.Provider>
);
}
function DeepComponent() {
const { theme, setTheme } = useContext(ThemeContext);
return <button onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}>{theme}</button>;
}39. Controlled vs uncontrolled components?
// Controlled
function ControlledForm() {
const [email, setEmail] = useState('');
return <input value={email} onChange={e => setEmail(e.target.value)} />;
}
// Uncontrolled
function UncontrolledForm() {
const emailRef = useRef(null);
return <form onSubmit={() => console.log(emailRef.current.value)}>
<input ref={emailRef} defaultValue="" />
</form>;
}40. How does `useReducer` work?
function cartReducer(state, action) {
switch (action.type) {
case 'ADD_ITEM': return { ...state, items: [...state.items, action.item] };
case 'REMOVE_ITEM': return { ...state, items: state.items.filter(i => i.id !== action.id) };
default: return state;
}
}
function Cart() {
const [state, dispatch] = useReducer(cartReducer, { items: [] });
return (
<div>
{state.items.map(item => (
<CartItem key={item.id} item={item}
onRemove={() => dispatch({ type: 'REMOVE_ITEM', id: item.id })} />
))}
</div>
);
}useReducer when state has multiple sub-values or complex transitions. Use useState for simple independent values.Section 7: TypeScript
41. What is the difference between `interface` and `type` in TypeScript?
interface User { id: number; name: string; }
interface User { email: string; } // declaration merging
interface Admin extends User { role: 'admin'; }
type User = { id: number; name: string; };
type Admin = User & { role: 'admin' };
type ID = string | number; // union — only type can do this
type Nullable<T> = T | null;interface supports declaration merging; type is more flexible for unions and utility types.42. What are TypeScript generics?
function first<T>(arr: T[]): T { return arr[0]; }
const n = first([1, 2, 3]); // n: number
const s = first(['a', 'b']); // s: string
interface ApiResponse<T> { data: T; status: number; }
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}Section 8: Accessibility
43. What is ARIA and when should you use it?
<!-- Use native HTML first -->
<button>Submit</button>
<!-- ARIA only when HTML falls short -->
<div role="dialog" aria-modal="true" aria-labelledby="title">
<h2 id="title">Confirm</h2>
</div>
<button aria-label="Close menu">
<svg aria-hidden="true" focusable="false">...</svg>
</button>
<div aria-live="polite"><span id="status"></span></div>44. How do you handle keyboard navigation in custom components?
function Dropdown({ items }) {
const [open, setOpen] = useState(false);
const [focusIndex, setFocusIndex] = useState(-1);
function handleKeyDown(e) {
switch (e.key) {
case 'ArrowDown': e.preventDefault(); setFocusIndex(i => Math.min(i + 1, items.length - 1)); break;
case 'ArrowUp': e.preventDefault(); setFocusIndex(i => Math.max(i - 1, 0)); break;
case 'Escape': setOpen(false); break;
case 'Enter': setOpen(o => !o); break;
}
}
return (
<div>
<button aria-haspopup="listbox" aria-expanded={open} onKeyDown={handleKeyDown}>
Select option
</button>
{open && (
<ul role="listbox">
{items.map((item, i) => (
<li key={item.id} role="option" aria-selected={i === focusIndex} tabIndex={i === focusIndex ? 0 : -1}>
{item.label}
</li>
))}
</ul>
)}
</div>
);
}Section 9: Networking and Security
45. What is CORS and how does it work?
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://app.example.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (req.method === 'OPTIONS') return res.sendStatus(200);
next();
});46. What is XSS and how do you prevent it?
// Safe
element.textContent = userInput;
element.innerHTML = DOMPurify.sanitize(userHtml);
// Dangerous
element.innerHTML = userInput; // never
// React is safe by default
return <div>{userInput}</div>; // auto-escaped
return <div dangerouslySetInnerHTML={{ __html: userInput }} />; // dangerous47. What is the difference between authentication and authorization?
// 401 Unauthorized = not authenticated
// 403 Forbidden = authenticated but not authorizedSection 10: Build Tools and Toolchain
48. What is the difference between Webpack and Vite?
49. What is tree shaking?
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; } // unused — removed from bundle50. What is code splitting and how do you implement it in React?
const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
function App() {
return (
<Suspense fallback={<PageLoader />}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Suspense>
);
}Section 11: Testing
51. What is the difference between unit, integration, and end-to-end tests?
// Unit — pure function
expect(formatPrice(1234.5, 'USD')).toBe('$1,234.50');
// Integration — component behavior
render(<SearchBar onSearch={mockSearch} />);
await userEvent.type(screen.getByRole('textbox'), 'react hooks');
await userEvent.click(screen.getByRole('button', { name: /search/i }));
expect(mockSearch).toHaveBeenCalledWith('react hooks');
// E2E — Playwright full browser
await page.goto('/login');
await page.fill('[name=email]', 'user@example.com');
await page.click('button[type=submit]');
await expect(page).toHaveURL('/dashboard');52. What is the difference between mocking and spying in tests?
const consoleSpy = vi.spyOn(console, 'log');
vi.mock('./api', () => ({ fetchUser: vi.fn().mockResolvedValue({ id: 1 }) }));Bonus: System Design and Architecture
53. How would you architect a large frontend application?
src/
├── app/ # routing, providers, global layouts
├── features/ # auth/, dashboard/, search/ — each has components/, hooks/, api/, types.ts
├── shared/ # Button, Modal, useDebounce, utils
├── lib/ # axios instance, query client
└── types/ # global TypeScript types54. How do you approach performance optimization in a slow React app?
React.memo, useCallback, useMemonpx vite-bundle-visualizerimport { useVirtualizer } from '@tanstack/react-virtual';
function VirtualList({ items }) {
const parentRef = useRef(null);
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 60,
});
return (
<div ref={parentRef} style={{ height: '500px', overflow: 'auto' }}>
<div style={{ height: virtualizer.getTotalSize() }}>
{virtualizer.getVirtualItems().map(vItem => (
<div key={vItem.key} style={{ position: 'absolute', top: vItem.start, height: vItem.size }}>
{items[vItem.index].name}
</div>
))}
</div>
</div>
);
}How to Use This Guide
FAQ
What frontend interview questions come up most often?+
How do I prepare for a senior frontend developer interview?+
Do I need to know TypeScript for a frontend interview in 2026?+
What React hooks questions should I prepare for?+
How do closures work in JavaScript?+
What is the difference between Flexbox and CSS Grid?+
How do I prevent XSS attacks in a frontend application?+
What should I know about accessibility for a frontend interview?+
Related articles
Prepare for your real interview
