Frontend Developer interview questions
100 real questions with model answers and explanations for Middle candidates.
See a Frontend Developer resume example →Questions
The event loop drains the whole microtask queue after each macrotask, before the next render.
- Microtasks: Promises, queueMicrotask, MutationObserver; they all run before rendering.
- Macrotasks: setTimeout, setInterval, I/O; setTimeout(..., 0) yields to the render cycle.
- Long .then() chains can starve rendering and freeze the UI.
- Knowing the order lets you predict execution and avoid jank.
Why interviewers ask this: Tests whether the candidate understands JavaScript concurrency beyond just knowing the language is single-threaded.
A closure is a function that keeps access to variables from its enclosing scope after that scope has finished.
- It captures the outer variables by reference, not by copy.
- Classic example: a makeCounter factory returning increment and decrement that share one private count.
- It powers the module pattern and memoization helpers.
Why interviewers ask this: Evaluates whether the candidate can apply the concept practically, not just recite a textbook definition.
All three set a function's this explicitly, but differ in how and when they invoke it.
- call: invokes immediately, arguments passed individually.
- apply: invokes immediately, arguments passed as an array.
- bind: returns a new function with this permanently bound, without calling it.
- bind is common for passing class methods as callbacks without losing context.
Why interviewers ask this: Checks practical understanding of this binding, not just syntax memorization.
Every object links to another via [[Prototype]], forming a chain that ends at Object.prototype.
- Property lookups walk the chain until the property is found or the chain ends.
- ES6 class syntax is sugar over the same prototype-based inheritance.
- Class methods land on the constructor's prototype, not on each instance.
Why interviewers ask this: Reveals whether the candidate understands that classes do not introduce a new inheritance model, which matters when debugging unexpected prototype behavior.
They differ in when they settle and how they treat rejections.
- Promise.all: resolves when all resolve, rejects on the first rejection.
- Promise.allSettled: waits for all to settle, returns status objects regardless of outcome.
- Promise.race: settles as soon as the first promise settles, resolve or reject.
- Promise.any: resolves on the first resolve, rejects only if all reject.
Why interviewers ask this: Tests whether the candidate can select the right combinator for a given async coordination scenario.
Reach for WeakMap or WeakSet when you want keys that the garbage collector can reclaim.
- They hold weak references, so an object is collected once no strong reference remains.
- Ideal for metadata about DOM nodes or objects without blocking garbage collection.
- They have no iteration methods, so avoid them when you need to enumerate entries.
Why interviewers ask this: Assesses understanding of memory management in long-running single-page applications.
Debounce waits for a pause; throttle caps the rate; pick by the event.
- Debounce: runs only after calls stop for a set time, ideal for search-as-you-type.
- Throttle: runs at most once per interval, ideal for scroll or resize handlers.
- Debounce on scroll feels worse than throttle because nothing fires while scrolling.
Why interviewers ask this: Evaluates practical knowledge of performance patterns for high-frequency browser events.
Memoization caches a pure function's result by its arguments so repeat calls return instantly.
- Implement it with a Map or a closure-held cache object.
- Main trade-off: memory grows with unique argument combinations and can leak with object keys.
- In React, useMemo and useCallback are built in but add overhead when deps change often.
Why interviewers ask this: Tests the ability to weigh the performance benefits of caching against memory costs.
Regular functions get their own this from the call site; arrow functions inherit it lexically.
- Regular: this depends on how it is called (method, constructor, call/apply, or default).
- Arrow: captures this from the enclosing scope at definition time.
- This makes arrows unreliable as object methods but ideal as callbacks inside class methods.
Why interviewers ask this: A classic source of bugs in real codebases; tests whether the candidate can diagnose this-related errors quickly.
They differ in copy depth and what they can preserve.
- Spread: shallow copy, only top-level references are duplicated.
- JSON.parse(JSON.stringify()): deep clone, but loses functions, turns Dates into strings, drops undefined, throws on cycles.
- structuredClone: true deep clone handling Dates, typed arrays, and cycles, but not functions or DOM nodes.
Why interviewers ask this: Tests awareness of pitfalls that cause subtle bugs when working with nested state or complex data structures.
async/await is syntactic sugar over Promises.
- An async function always returns a Promise.
- await pauses the function and yields to the event loop until the awaited Promise settles, then resumes.
- Babel compiles it into a state machine with generator-like semantics and .then() chains.
- Awaiting a non-Promise still works because it is wrapped in Promise.resolve().
Why interviewers ask this: Ensures the candidate understands async/await as built on Promises, preventing misconceptions about blocking behavior.
They differ in load timing, structure, and binding semantics.
- CommonJS: require/module.exports, loaded synchronously, evaluated at runtime, mutable exports.
- ES modules: import/export, static structure analyzed at parse time, enabling tree shaking.
- ES modules are always async in browsers; Node supports both.
- ES module live bindings mean an import reflects the latest export value.
Why interviewers ask this: Important for understanding why certain libraries are not tree-shakeable and why mixing module systems causes issues in bundlers.
A generator uses function* and can pause with yield, returning an iterator.
- It produces values on demand instead of computing everything upfront.
- Useful for pagination in infinite scroll.
- Useful for complex async control flow in libraries like redux-saga.
- Useful for lazy sequences.
Why interviewers ask this: Tests depth of JavaScript knowledge; generators are a niche but powerful feature that separates broadly knowledgeable candidates from those who only use common patterns.
Find the leak with heap snapshots, then fix the source that keeps references alive.
- Common causes: global listeners never removed, closures holding large module-scope data, subscriptions not cleaned on unmount.
- Detect: take heap snapshots in Chrome DevTools Memory before and after navigating, compare retained sizes.
- Fix: remove listeners in cleanup functions, use WeakMap for metadata, unsubscribe from WebSocket or Observable streams on unmount.
Why interviewers ask this: Evaluates production-level debugging ability and awareness of memory issues specific to long-lived SPAs.
The temporal dead zone is the gap between entering a scope and reaching a let or const declaration.
- Accessing the variable in its TDZ throws a ReferenceError even though it exists in scope.
- This differs from var, which is hoisted and initialized to undefined.
- TDZ errors show up in class field initializers and when reading a variable before its declaration.
Why interviewers ask this: Distinguishes candidates with deep hoisting knowledge from those who only know that let and const behave differently from var.
React diffs the previous and new virtual DOM trees to decide what to re-render.
- It assumes different element types produce different trees and skips matching subtrees.
- The key prop signals element identity across renders, so a DOM node can be reused when its list position changes.
- Without correct keys, React may destroy and recreate expensive components, hurting performance and losing local state.
Why interviewers ask this: Fundamental to React performance; a candidate who understands reconciliation can diagnose most unnecessary re-render bugs.
useCallback memoizes a function reference; useMemo memoizes a computed value.
- useCallback: keeps a stable function reference so memoized children do not re-render needlessly.
- useMemo: avoids expensive recalculations on every render.
- Use useCallback for stable props to memoized children; use useMemo for costly computations.
- Both are often overused, adding overhead when dependencies change frequently.
Why interviewers ask this: Tests judgment about when memoization actually helps, not just whether the candidate knows the hooks exist.
A controlled component is driven by React state; an uncontrolled one manages its own value via a ref.
- Controlled: value comes from state plus an onChange handler, so React is the source of truth.
- Uncontrolled: state lives in the DOM, read via inputRef.current.value.
- Controlled fits validation, conditional rendering, and multi-field sync.
- Uncontrolled is simpler for file inputs or third-party DOM libraries.
Why interviewers ask this: Reveals understanding of data flow and form handling, one of the most common sources of bugs in React applications.
Hooks must run at the top level of a React function, in the same order every render.
- Do not call them inside loops, conditions, or nested functions.
- Call them only from React components or custom hooks, not plain JavaScript.
- React matches each hook to its state by call order; breaking the order misassigns state.
Why interviewers ask this: Understanding the reason behind the rules prevents the hard-to-diagnose bugs caused by conditional hook calls.
React.memo skips a component's re-render when its props are shallow-equal.
- It does not help when props are objects or functions recreated on every parent render.
- Shallow comparison sees those new references as changed.
- Pair it with useCallback and useMemo in the parent for the optimization to work.
- The comparison overhead is wasted if the component is cheap to render.
Why interviewers ask this: Tests whether the candidate can identify when memoization is counterproductive rather than applying it blindly.
Locked questions
- 21
How do error boundaries work in React and what do they not catch?
react - 22
What are the performance pitfalls of React Context?
reactperformance - 23
When would you choose useReducer over useState?
hooks - 24
What is React.lazy and how does Suspense support code splitting?
react - 25
What changed about state batching in React 18?
reactbatch - 26
Why is using array index as the key prop in a list problematic?
indexes - 27
How do you implement virtualization for a long list and when is it necessary?
virtualization - 28
What is the purpose of the useEffect cleanup function and how does it differ from componentWillUnmount?
componentshooks - 29
What is React.forwardRef and when do you need it?
react - 30
How do you diagnose a slow render using React DevTools Profiler?
react - 31
What is the Compound Component pattern and what problem does it solve?
components - 32
How do you share state between two sibling components that have no close common parent?
components - 33
How do stale closures occur in useEffect and how do you fix them?
hooksclosures - 34
What is concurrent rendering in React 18 and how does it change UI behavior?
reactconcurrency - 35
What is the render props pattern and how does it compare to custom hooks?
hooks - 36
What is the difference between interface and type alias in TypeScript and when do you choose each?
typescripttypes - 37
How do you use generics in a React component to make it reusable across different data types?
reactcomponentsgenerics - 38
What are TypeScript conditional types and can you give a practical example?
typescript - 39
What is the infer keyword in TypeScript and how do you use it?
typescript - 40
What is type narrowing in TypeScript and what techniques can you use?
typescript - 41
What are discriminated unions in TypeScript and why are they useful?
typescript - 42
How do you add types for a third-party JavaScript library that has no TypeScript definitions?
typescriptjavascript - 43
How do you write a function overload in TypeScript to handle different argument combinations?
typescript - 44
When would you use CSS Grid over Flexbox and when would you use Flexbox?
cssflexboxgrid - 45
How does CSS specificity work and how do you resolve conflicts without resorting to !important?
css - 46
What are CSS custom properties and how are they different from Sass or Less variables?
css - 47
What is a CSS stacking context and why does it affect z-index behavior?
cssindexes - 48
What is the difference between em, rem, vh, vw, and ch units and when do you use each?
css - 49
How do you build a responsive layout without media queries using modern CSS?
cssresponsivequeries - 50
How do you prevent cumulative layout shift in practice?
web-vitals - 51
What is CSS containment and when should you apply it?
css - 52
What are Core Web Vitals and how do you measure them in production?
web-vitals - 53
What strategies do you use to reduce JavaScript bundle size?
bundle-sizejavascript - 54
How does tree shaking work and what are the common reasons it fails?
tree-shaking - 55
What is the difference between Webpack and Vite in development and why is Vite faster?
webpackvite - 56
What is Hot Module Replacement and how does it preserve component state during development?
componentshmr - 57
How do source maps work and when should you enable them in production?
source-maps - 58
How do you analyze a frontend bundle to find performance bottlenecks?
performance - 59
What is the purpose of a linter versus a formatter and how do they work together?
linting - 60
How do you handle environment variables in a frontend build securely?
soft-skillsconfig - 61
What is code splitting and how do you implement it in a React application?
react - 62
How does browser caching work and how do you ensure users receive the latest code after a deploy?
cachingdeployment - 63
What image formats should you use for different cases and how do you choose between them?
images - 64
How do you optimize web fonts to reduce layout shift and render-blocking behavior?
optimizationweb-vitals - 65
What is the difference between SSR, SSG, CSR, and ISR and when do you choose each?
ssr - 66
What is the difference between unit, integration, and end-to-end tests in frontend development?
e2e - 67
How do you test a React component that makes API calls without hitting a real server?
reactcomponentsapi - 68
How do you test custom React hooks?
reacthooks - 69
What does "test behavior, not implementation" mean and how do you apply it?
- 70
When is snapshot testing useful and when does it become a liability?
snapshot - 71
What is visual regression testing and which tools support it?
visual - 72
How do you handle async state updates in tests to avoid flaky assertions?
soft-skillsasynctesting - 73
What is Flux architecture and how does Redux implement it?
statearchitecture - 74
What are the trade-offs between Redux Toolkit, Zustand, and React Query for state management?
reactstatequeries - 75
What is the difference between server state and UI state and why should they be managed separately?
state - 76
How do you implement optimistic UI updates?
locking - 77
What is prop drilling and what solutions exist?
state - 78
How do you persist state across page refreshes?
state - 79
How do you design a scalable folder structure for a large React application?
designstructurereact - 80
What is a design system and what does it include beyond a component library?
componentsdesign-systemsystem-design - 81
What is the BFF (Backend for Frontend) pattern and when is it beneficial?
- 82
When would you consider micro-frontends and what are the main trade-offs?
micro-frontends - 83
How do you manage breaking API changes on the frontend when the backend evolves?
api - 84
How do you diagnose a component that re-renders more often than expected?
components - 85
How do you debug a memory leak in a React application?
memoryreact - 86
A performance regression appeared in production but you cannot reproduce it locally. How do you investigate?
performance - 87
An API call fails intermittently in production but works consistently in development. How do you investigate?
api - 88
CSS works in Chrome but breaks in Safari. How do you approach the cross-browser debugging?
css - 89
How do you debug a hydration mismatch error in a server-rendered React application?
reacthydration - 90
What tools do you use to diagnose slow JavaScript execution?
javascript - 91
What is the difference between ARIA roles and native HTML semantic elements for accessibility?
htmla11y - 92
How do you ensure keyboard navigation works correctly inside a modal dialog?
a11y - 93
What is color contrast ratio and how do you verify it meets WCAG standards?
a11y - 94
How do you make a dynamically updated content region accessible to screen readers?
a11y - 95
How do you implement a fully accessible custom dropdown component?
components - 96
Describe how you identified and resolved a significant performance issue in a production application.
performance - 97
How do you handle a task where the requirements are unclear or conflicting?
soft-skills - 98
How do you handle a code review where you strongly disagree with the reviewer's feedback?
soft-skillsconflictfeedback - 99
How do you approach refactoring a large legacy component without breaking existing behavior?
refactoringcomponents - 100
How do you stay current with the rapidly changing frontend ecosystem without it consuming all your time?
learning