All interview questions Web · 2026

JavaScript Interview Questions

JavaScript is tested in almost every frontend and full-stack interview, and the questions are unusually consistent. These are the ones that come up again and again, grouped by theme and tagged by experience level.

101 questions with concise, interview-ready answers.

JavaScript Fundamentals

1. What is the difference between var, let, and const? Fresher

var is function-scoped and hoisted with an initial value of undefined, so it can be read before its declaration. let and const are block-scoped and hoisted into a "temporal dead zone", so reading them before declaration throws a ReferenceError. const prevents reassignment of the binding, not mutation of the object it points to.

2. What is the difference between == and ===? Fresher

=== compares value and type with no conversion. == performs type coercion first, which produces surprising results — "1" == 1 is true, null == undefined is true, and [] == false is true. Use === by default; the one common exception is x == null to test for null or undefined together.

3. What is the difference between null and undefined? Fresher

undefined means a variable has been declared but not assigned, or a property does not exist — it is what JavaScript gives you by default. null is an explicit assignment meaning "no value". typeof undefined is "undefined"; typeof null is "object", which is a long-standing bug in the language kept for backward compatibility.

4. What are the primitive types in JavaScript? Fresher

string, number, boolean, null, undefined, symbol and bigint. Everything else — objects, arrays, functions, dates — is an object. Primitives are compared by value and are immutable; objects are compared by reference.

5. What is hoisting? Fresher

Declarations are processed before code runs. Function declarations are hoisted entirely and callable before their definition. var declarations are hoisted and initialised to undefined. let and const are hoisted but uninitialised, so accessing them early throws. Function expressions and arrow functions assigned to variables follow the variable rules, not the function ones.

6. What values are falsy in JavaScript? Fresher

false, 0, -0, 0n, "", null, undefined and NaN. Everything else is truthy — including empty arrays and empty objects, which is the trap. That is why checking `if (arr)` does not tell you whether an array has elements; you need arr.length.

7. What is type coercion? Fresher

Automatic conversion between types when operators are applied to mismatched operands. + prefers string concatenation if either side is a string, so 1 + "2" is "12", while - has no string meaning so "3" - 1 is 2. This asymmetry is the source of most JavaScript quiz questions.

8. What is NaN, and how do you test for it? Fresher

NaN means "not a number" and is the result of an invalid numeric operation. It is the only value in JavaScript not equal to itself, so NaN === NaN is false. Test with Number.isNaN(x), which checks the value; the older global isNaN() coerces first, so isNaN("abc") is confusingly true.

9. What is the difference between a function declaration and a function expression? 2–5 yrs

A declaration — function f() {} — is fully hoisted, so you can call it before it appears. An expression — const f = function() {} — is only assigned when execution reaches it, so calling earlier throws. Named function expressions also keep their name in stack traces, which helps debugging.

10. What is the difference between an arrow function and a regular function? 2–5 yrs

Arrow functions have no own `this` — they inherit it lexically from the enclosing scope — no `arguments` object, and cannot be used as constructors or with `new`. They also cannot be given a `this` via call, apply or bind. That lexical `this` is exactly why they solved the callback binding problem.

11. What is strict mode? 2–5 yrs

"use strict" opts into stricter parsing: assigning to an undeclared variable throws instead of creating a global, `this` is undefined rather than the global object in plain function calls, duplicate parameter names are errors, and some silent failures become throws. ES modules and class bodies are always strict.

12. What is the difference between pass by value and pass by reference in JavaScript? 2–5 yrs

Primitives are passed by value — the function gets a copy. Objects are passed by a copy of the reference, so mutating properties inside the function is visible to the caller, but reassigning the parameter is not. Strictly this is "pass by sharing", and describing it that way scores well.

13. Why is 0.1 + 0.2 not equal to 0.3? Senior

Numbers are IEEE-754 double-precision floats, and 0.1 and 0.2 have no exact binary representation, so the sum carries a tiny error. Compare with a tolerance — Math.abs(a - b) < Number.EPSILON — or work in integers (cents rather than pounds) for money, or use a decimal library.

14. What is the temporal dead zone? Senior

The window between a let or const binding being hoisted into scope and its declaration being evaluated. During it the binding exists but reading it throws a ReferenceError. It exists deliberately, so that use-before-declaration is an error rather than silently undefined the way var is.

Scope, Closures & this

15. What is a closure? Fresher

A function that retains access to variables from the scope where it was created, even after that scope has returned. It is how you get private state, function factories and memoisation. Every callback that reads an outer variable is a closure — the concept is more common than the name suggests.

16. How does the "this" keyword work in JavaScript? Fresher

`this` is determined by how a function is called, not where it is defined. As a method it is the object before the dot; called standalone it is undefined in strict mode or the global object otherwise; with new it is the new instance; with call, apply or bind it is whatever you pass. Arrow functions ignore all of this and take `this` lexically.

17. What is the difference between call, apply and bind? Fresher

call and apply invoke the function immediately with an explicit `this` — call takes arguments individually, apply takes them as an array. bind does not invoke; it returns a new function permanently bound to that `this`, optionally with preset leading arguments (partial application).

18. What is the difference between global, function and block scope? Fresher

Global scope is accessible everywhere. Function scope is created by every function and is what var respects. Block scope is created by any pair of braces and is what let and const respect. The classic loop bug — all callbacks seeing the final value of a var counter — is a function-versus-block scope problem.

19. What is the scope chain? 2–5 yrs

When a name is not found in the current scope, the engine looks in the enclosing scope, and so on out to global, throwing a ReferenceError if it is never found. The chain is fixed at definition time, not call time — which is what makes JavaScript lexically scoped and what makes closures work.

20. Why does a var inside a for loop with a setTimeout print the same number? 2–5 yrs

var is function-scoped, so all iterations share one binding, and by the time the timeouts fire the loop has finished and that single variable holds its final value. Change var to let, which creates a fresh binding per iteration, or wrap the body in an IIFE to capture the value.

21. What is an IIFE and what was it for? 2–5 yrs

An immediately invoked function expression — (function(){ ... })() — used to create a private scope before block scoping existed, keeping variables out of the global namespace. It was the foundation of the module pattern. With let, const and ES modules it is largely historical, though it still appears in bundled output.

22. What is currying? 2–5 yrs

Transforming a function of several arguments into a chain of single-argument functions, so f(a, b, c) becomes f(a)(b)(c). It is built on closures and is useful for creating specialised functions from general ones — a log function partially applied with a level, for instance.

23. How can closures cause memory leaks? Senior

A closure keeps its entire enclosing scope alive, not just the variables it uses, so a long-lived callback can retain a large object indefinitely. Event listeners attached and never removed are the common case in browsers, and a closure over a DOM node keeps the node out of the garbage collector even after removal from the document.

24. How do you implement a private field in JavaScript? Senior

Modern answer: a #private class field, which is enforced by the language and inaccessible from outside. Historically you used a closure over a local variable in a factory function, or a WeakMap keyed by instance. The underscore convention is not privacy, only a signal.

25. What does "use strict" change about `this`? Senior

In a plain function call, non-strict code substitutes the global object for an undefined `this`, which silently allows accidental global mutation. Strict mode leaves it undefined, so the mistake throws. Class bodies and modules are strict by default, which is why `this` is undefined in an unbound extracted method.

26. What is the module pattern and how do ES modules differ? Senior

The module pattern used an IIFE returning an object of public methods, with everything else closed over and private. ES modules are a language feature with static import and export, hoisted and analysable at build time, always strict, and with live bindings rather than copied values — which is what enables tree shaking.

Objects & Prototypes

27. What is prototypal inheritance? Fresher

Every object has an internal link to a prototype object, and property lookups that miss walk up that prototype chain until they hit null. Methods are shared by living on the prototype rather than being copied per instance. class syntax is sugar over this — it does not introduce a different inheritance model.

28. What is the difference between a shallow copy and a deep copy? Fresher

A shallow copy — Object.assign({}, obj) or {...obj} — duplicates the top level but shares references to nested objects, so mutating a nested value is visible through both. A deep copy duplicates the whole graph; structuredClone() does it natively, handling cycles, Maps and Dates, which JSON.parse(JSON.stringify(x)) does not.

29. How do you check whether an object has a property? Fresher

Object.hasOwn(obj, key) is the modern answer and checks own properties only. The `in` operator also finds inherited properties. obj[key] !== undefined is unreliable, because a property explicitly set to undefined exists but fails that test.

30. What is the difference between Object.keys, Object.values and Object.entries? Fresher

They return arrays of an object's own enumerable string-keyed property names, values, or [key, value] pairs respectively. entries is what makes an object iterable with for...of and destructuring. All three skip inherited and symbol-keyed properties.

31. What is the difference between a class and a constructor function? 2–5 yrs

Behaviourally they are close — both create objects whose methods live on a prototype. Classes add real differences: they are not hoisted in a usable way, their bodies are always strict, methods are non-enumerable, and calling one without new throws. Classes also support extends, super, static members and #private fields cleanly.

32. What is the difference between Object.freeze and const? 2–5 yrs

const prevents reassigning the binding; the object it points to can still be mutated. Object.freeze prevents adding, removing or changing properties of the object, but only one level deep — nested objects remain mutable, so a genuine deep freeze needs recursion.

33. What are getters and setters? 2–5 yrs

Accessor properties defined with get and set that run a function when a property is read or written, while looking like a plain property to callers. They let you add validation or computation later without changing call sites. Watch for infinite recursion from a setter assigning to its own property name.

34. What is optional chaining and nullish coalescing? 2–5 yrs

?. short-circuits to undefined instead of throwing when the left side is null or undefined — obj?.a?.b, and also arr?.[i] and fn?.(). ?? returns the right side only when the left is null or undefined, unlike ||, which also replaces 0 and "". Together they remove most defensive-guard boilerplate.

35. What is the difference between Map and a plain object? 2–5 yrs

A Map accepts any value as a key including objects, preserves insertion order, exposes .size, and is iterable directly. Object keys are coerced to strings or symbols, and objects carry prototype keys you must guard against. Use Map for a genuine dictionary with dynamic or non-string keys.

36. What is a WeakMap and when is it useful? Senior

A Map whose keys are held weakly, so an entry does not prevent its key object from being garbage collected. That makes it right for attaching metadata or private state to objects you do not own — DOM nodes, for instance — without leaking when they are removed. It is not iterable, precisely because entries can vanish.

37. What is a Proxy? Senior

An object that wraps another and intercepts fundamental operations — get, set, has, deleteProperty — through handler traps. It powers reactivity systems like Vue 3 and validation or logging layers. The cost is a real performance penalty on every intercepted operation and harder debugging.

38. How does instanceof work, and when does it fail? Senior

It walks the prototype chain of the left operand looking for the right operand's .prototype. It fails across execution contexts — an array from an iframe or worker is not instanceof the local Array — and it can be fooled by reassigning prototypes. Array.isArray and typeof checks are more robust for built-ins.

Arrays & Iteration

39. What is the difference between map, filter and reduce? Fresher

map returns a new array of the same length with each element transformed. filter returns a new, possibly shorter array of elements passing a predicate. reduce folds the array into a single accumulated value, which can itself be an array or object. All three are non-mutating and return new values.

40. What is the difference between forEach and map? Fresher

map returns a new array; forEach returns undefined and exists purely for side effects. Neither can be broken out of early — use a for...of loop or .some() for that. Using map purely for side effects and discarding the result is a common review comment.

41. What are the spread and rest operators? Fresher

Both use `...`. Spread expands an iterable into elements or an object into properties — [...arr], {...obj}, f(...args) — and gives a convenient shallow copy. Rest collects the remainder into an array or object — function f(a, ...rest), or const {a, ...others} = obj. Same syntax, opposite direction.

42. What is destructuring? Fresher

Extracting values from arrays or properties from objects into variables: const [a, b] = arr, const {name, age} = user. It supports defaults, renaming (const {name: userName}), nesting, and works in function parameters — which is how most React props are read.

43. What is the difference between slice and splice? Fresher

slice returns a shallow copy of a portion and does not modify the original. splice mutates the array in place, removing and optionally inserting elements, and returns the removed ones. The name similarity makes this a reliable interview question.

44. What is the difference between find, findIndex, some and every? 2–5 yrs

find returns the first matching element or undefined; findIndex returns its index or -1. some returns true if any element matches, every returns true only if all do. All four short-circuit on the first decisive element, unlike filter, which always walks the whole array.

45. What is the difference between for...in and for...of? 2–5 yrs

for...in iterates enumerable property keys, including inherited ones, and on an array gives you string indices — which is why it is the wrong tool for arrays. for...of iterates values of any iterable: arrays, strings, Maps, Sets, generators. Use for...of for values and Object.keys for object keys.

46. How does Array.prototype.sort behave by default? 2–5 yrs

It sorts in place and converts elements to strings, so [10, 9, 1].sort() gives [1, 10, 9]. Always pass a comparator for numbers: (a, b) => a - b. Sort has been required to be stable since ES2019, so equal elements keep their relative order.

47. How do you flatten a nested array? 2–5 yrs

arr.flat() flattens one level, arr.flat(Infinity) flattens fully, and flatMap maps then flattens one level in a single pass. Before those existed you used reduce with concat and recursion, which is still worth being able to write if the interviewer bans the built-in.

48. How do you remove duplicates from an array? 2–5 yrs

[...new Set(arr)] for primitives — concise and O(n). For objects, Set compares by reference, so dedupe on a key instead: build a Map keyed by that field and take its values. Say which case you are handling; the object case is where the interesting answer is.

49. What makes an object iterable? Senior

A [Symbol.iterator] method returning an iterator — an object with next() returning { value, done }. Implementing it makes your object work with for...of, spread and destructuring. Generator functions produce this protocol automatically, which is why they are the easy way to make something iterable.

50. What are the new non-mutating array methods in recent JavaScript? Senior

toSorted, toReversed, toSpliced and with return new arrays instead of mutating in place, and at() supports negative indices so arr.at(-1) is the last element. They exist because accidental mutation of shared arrays is a persistent bug source, particularly in React state.

Async JavaScript

51. What is the event loop? Fresher

JavaScript runs on a single thread with a call stack. When the stack empties, the event loop takes the next callback from a queue and runs it. Long synchronous work therefore blocks everything, including rendering — which is why heavy computation belongs in a Web Worker.

52. What is the difference between callbacks, promises and async/await? Fresher

Callbacks pass a function to be invoked later and nest badly, producing callback hell and awkward error handling. Promises are objects representing a future value, chainable with .then and .catch. async/await is syntax over promises that reads like synchronous code and lets you use try/catch. All three are the same underlying mechanism.

53. What are the states of a promise? Fresher

pending, fulfilled or rejected. Once it settles — fulfilled or rejected — the state and value are immutable. .then, .catch and .finally register callbacks that run asynchronously as microtasks, even if the promise has already settled.

54. What is the difference between microtasks and macrotasks? Fresher

Microtasks — promise callbacks and queueMicrotask — run after the current synchronous execution and before the next macrotask, and the whole microtask queue is drained each time. Macrotasks — setTimeout, setInterval, I/O — run one per loop iteration. That is why a promise callback fires before a setTimeout(0) scheduled earlier.

55. What is the difference between Promise.all, allSettled, race and any? 2–5 yrs

all resolves with every result or rejects on the first failure. allSettled always resolves with a status for each, never rejecting. race settles with the first promise to settle either way. any resolves with the first fulfilment and rejects only if all fail. Use allSettled when partial failure is acceptable.

56. How do you handle errors with async/await? 2–5 yrs

Wrap the await in try/catch, or attach .catch to the returned promise. The common bug is forgetting await inside a try — the promise rejects outside the block and becomes an unhandled rejection. Also remember that an async function always returns a promise, so its caller must handle rejection too.

57. How do you run async operations in parallel rather than in series? 2–5 yrs

Sequential awaits in a loop wait for each in turn. Start them all first, then await together: const results = await Promise.all(items.map(fetchOne)). The distinction matters enormously — a loop of ten 200ms calls takes two seconds serially and 200ms in parallel.

58. What is a race condition in async JavaScript, and how do you avoid it? 2–5 yrs

Two async operations completing in an unpredictable order and clobbering each other — typically a stale search response overwriting a newer one. Fix it by cancelling superseded requests with AbortController, or by tagging each request and discarding responses that are no longer current.

59. What is the difference between setTimeout and setInterval, and what is the drift problem? 2–5 yrs

setTimeout schedules once; setInterval repeats. Neither is precise — the delay is a minimum, because the callback waits for an empty stack. setInterval also drifts and can overlap if the callback takes longer than the interval, which is why a recursive setTimeout is usually the safer repeating pattern.

60. What is an unhandled promise rejection and why does it matter? Senior

A rejected promise with no rejection handler. In browsers it fires an unhandledrejection event and logs; in Node it terminates the process by default in modern versions. It usually comes from a forgotten await or a missing .catch, and it means an error you never saw took down or silently broke something.

61. What is an async generator and when is it useful? Senior

A function declared async function* that yields promises, consumed with for await...of. It is the right shape for streaming — paginated API results, a file read in chunks, a message queue — because it applies backpressure naturally: nothing is produced until the consumer asks.

62. How would you implement a promise-based timeout? Senior

Promise.race between the real work and a promise that rejects after n milliseconds via setTimeout. To do it properly, clear the timer in a finally so it does not keep the event loop alive, and use AbortController to actually cancel the underlying request — otherwise you have only stopped waiting, not stopped the work.

63. How does Node.js achieve concurrency on a single thread? Senior

The event loop delegates I/O to the operating system or to libuv's thread pool, so the main thread never blocks waiting. Callbacks are queued and run when the stack clears. CPU-bound work still blocks everything, which is what worker threads and child processes exist for.

ES6+ Features

64. What are some key ES6 features? Fresher

let and const, arrow functions, template literals, destructuring, default and rest parameters, spread, classes, ES modules, promises, Map and Set, and symbols. ES6 (2015) is the release that changed how JavaScript is written day to day; later annual releases have been smaller and more targeted.

65. What are template literals? Fresher

Backtick strings supporting interpolation with ${...} and real multi-line content without escapes. They also support tagged templates, where a function receives the string parts and the interpolated values separately — which is how libraries like styled-components and safe SQL builders work.

66. What is the difference between default and named exports? Fresher

A module can have one default export, imported without braces and renameable freely, and any number of named exports, imported by their exact name in braces. Named exports are generally preferred because they are explicit, discoverable by autocomplete, and safer to refactor.

67. What is the difference between CommonJS and ES modules? 2–5 yrs

CommonJS uses require and module.exports, resolves synchronously at runtime, and copies values. ES modules use import and export, are statically analysable at build time, hoisted, always strict, and provide live bindings. Static analysis is what makes tree shaking possible; that is the practical difference.

68. What is a Symbol used for? 2–5 yrs

A unique primitive used as a property key that cannot collide with any other key, which makes it safe for adding metadata to objects you do not own. Well-known symbols hook into language behaviour — Symbol.iterator makes an object iterable, Symbol.asyncIterator does the async version.

69. What is a generator function? 2–5 yrs

A function declared function* that can pause at yield and resume, returning an iterator. It enables lazy sequences, infinite sequences, and two-way communication, since the value passed to next() becomes the result of the yield expression. Generators underpinned async/await implementations before native support.

70. What is the difference between Set and WeakSet? 2–5 yrs

A Set stores unique values of any type, is iterable, and exposes .size. A WeakSet stores objects only, holds them weakly so membership does not prevent collection, and is not iterable. Use WeakSet to tag objects — "have I already processed this?" — without leaking.

71. What is dynamic import? 2–5 yrs

import() returns a promise for a module, loading it at runtime rather than at parse time. It enables code splitting and lazy loading — a heavy chart library fetched only when the chart renders — and it works in conditionals, unlike static import.

72. What is tree shaking, and what prevents it? Senior

Eliminating unused exports at build time, made possible by the static structure of ES modules. It breaks when code has side effects at module scope, when you import a whole namespace, when a package ships only CommonJS, or when the bundler cannot prove an export is unused. The sideEffects field in package.json is how libraries signal this.

73. What are decorators and what are they for? Senior

Functions that annotate and modify classes, methods, fields or accessors declaratively with @ syntax. They are widely used in TypeScript frameworks like Angular and NestJS for dependency injection and metadata. Standardisation has taken a long time and the semantics have changed between proposal stages, so check what your toolchain implements.

74. What is the difference between structuredClone and JSON round-tripping? Senior

JSON.parse(JSON.stringify(x)) silently loses undefined, functions, Dates become strings, Maps and Sets become empty objects, and it throws on cycles. structuredClone handles Dates, Maps, Sets, ArrayBuffers and circular references natively. It still cannot clone functions or DOM nodes.

75. What is top-level await and where does it apply? Senior

The ability to use await outside an async function, at the top level of an ES module. It simplifies module initialisation that needs async setup, but it delays evaluation of every importing module until it resolves — so a slow top-level await becomes a startup cost for the whole graph. It is not available in CommonJS.

DOM & Browser

76. What is event delegation? Fresher

Attaching one listener to a common ancestor and using event.target to identify which descendant was interacted with, instead of one listener per element. It handles dynamically added elements automatically and uses far less memory on large lists. It relies on event bubbling.

77. What is event bubbling and capturing? Fresher

An event dispatched on an element first travels down from the root to the target (capture phase), then back up (bubble phase). Listeners default to the bubble phase; pass true or {capture: true} for capture. stopPropagation halts further travel; preventDefault cancels the browser's default action, which is a separate thing.

78. What is the difference between localStorage, sessionStorage and cookies? Fresher

localStorage persists until cleared and is per origin. sessionStorage is cleared when the tab closes. Both are roughly 5-10MB and are not sent with requests. Cookies are small (about 4KB), can be sent with every request automatically, and support expiry, HttpOnly and Secure flags — which is why auth tokens belong there rather than in localStorage.

79. What is the difference between defer and async on a script tag? Fresher

Both download the script without blocking parsing. defer executes after parsing completes, in document order — right for scripts that depend on the DOM or on each other. async executes as soon as it downloads, in unpredictable order — only right for genuinely independent scripts like analytics.

80. What is the difference between debounce and throttle? 2–5 yrs

Debounce delays execution until a quiet period has passed, so rapid events collapse into one call at the end — right for search-as-you-type. Throttle guarantees at most one call per interval regardless of event frequency — right for scroll and resize handlers where you want steady updates.

81. What is the difference between the DOM and the virtual DOM? 2–5 yrs

The DOM is the browser's live tree; mutating it can trigger layout and paint, which is expensive. A virtual DOM is an in-memory description that a framework diffs against the previous version to compute a minimal set of real mutations. It is not inherently faster than a well-targeted direct update — its value is that it makes declarative rendering practical.

82. What is reflow and repaint? 2–5 yrs

Reflow (layout) recalculates geometry and is expensive because it can cascade through the tree; repaint redraws pixels without changing layout. Reading a layout property like offsetHeight immediately after a write forces a synchronous reflow — do all reads, then all writes, and prefer transform and opacity, which can be composited without layout.

83. What is CORS? 2–5 yrs

A browser-enforced policy that blocks cross-origin responses unless the server opts in with Access-Control-Allow-Origin and related headers. Non-simple requests are preceded by a preflight OPTIONS. It is enforced by the browser, not the server, which is why the same request succeeds from curl — a point candidates frequently miss.

84. What is the difference between fetch and XMLHttpRequest? 2–5 yrs

fetch is promise-based, has a cleaner API, and supports streaming and AbortController for cancellation. XHR is callback-based and older, but exposes upload progress events, which fetch still does not. Note that fetch does not reject on HTTP error statuses — you must check response.ok yourself.

85. What is the critical rendering path? Senior

The sequence from HTML and CSS arriving to the first paint: parse HTML into the DOM, parse CSS into the CSSOM, combine into a render tree, layout, then paint. CSS is render-blocking and synchronous scripts are parser-blocking, so inlining critical CSS and deferring non-essential JavaScript are the standard levers for improving first paint.

86. What is a Web Worker and what are its limits? Senior

A script running on a separate thread, so CPU-heavy work does not block the UI. It has no DOM access and communicates by structured-cloned messages, so there is a serialisation cost. Use it for parsing large payloads, image processing or crypto; not for small tasks, where the message overhead dominates.

87. How do you prevent XSS in JavaScript? Senior

Never build HTML from untrusted input. Use textContent rather than innerHTML, let your framework escape interpolated values, and treat any dangerouslySetInnerHTML equivalent as requiring sanitisation with a library like DOMPurify. Add a Content Security Policy as defence in depth, and keep auth tokens in HttpOnly cookies so a successful XSS cannot read them.

Performance & Patterns

88. What is memoisation and how would you implement it? 2–5 yrs

Caching a function's results keyed by its arguments so repeated calls with the same input are free. Implement it with a closure over a Map, serialising the arguments as a key. It only applies to pure functions, and an unbounded cache is a memory leak — bound it or use a WeakMap when keying on objects.

89. What is the difference between deep equality and reference equality? 2–5 yrs

Reference equality (=== on objects) is true only for the same object. Deep equality compares structure and values recursively. This is why a re-render is triggered by a new object with identical contents in React, and why dependency arrays and memo comparisons need either stable references or an explicit comparator.

90. How would you handle an API call that must not be duplicated? 2–5 yrs

Cache the in-flight promise itself, keyed by the request, and return the same promise to subsequent callers until it settles — request deduplication. Combined with AbortController for cancellation, this is the core of what libraries like SWR and React Query do.

91. What is the difference between imperative and declarative code? 2–5 yrs

Imperative code describes the steps — a for loop mutating an accumulator. Declarative code describes the result — map, filter, reduce, or JSX describing a UI for given state. Declarative code is usually easier to reason about and compose; imperative code is sometimes necessary for performance or for genuinely stateful sequences.

92. How would you find a memory leak in a browser application? Senior

Take heap snapshots in DevTools before and after repeating the suspected interaction, then compare retained size and look for detached DOM nodes and growing arrays. Common causes: listeners never removed, timers never cleared, closures over large objects, and caches without eviction. The signal is a heap that does not return to baseline after garbage collection.

93. What is the difference between shallow and deep freezing, and why does immutability matter? Senior

Object.freeze is one level; deep freezing requires recursion. Immutability matters because it makes change detection cheap — a new reference means something changed — which is the basis of memoisation, undo stacks and time-travel debugging. The cost is allocation, which structural sharing libraries reduce.

94. What is the module federation or micro-frontend trade-off? Senior

Splitting a frontend so teams deploy independently, at the cost of duplicated dependencies, harder shared state, version skew between fragments, and a more complex build. It is an organisational solution to an organisational problem — worth it when independent deployment is genuinely blocking teams, and expensive otherwise.

95. How do you decide between server-side and client-side rendering? Senior

Server rendering gives faster first contentful paint and works for crawlers that do not execute JavaScript, at the cost of server load and a hydration step. Client rendering gives cheaper hosting and smoother in-app navigation but a slower first paint. Most real answers are hybrid — render the shell and critical content on the server, hydrate the interactive parts.

96. What causes a large JavaScript bundle, and how do you reduce it? Senior

Usually a handful of heavy dependencies, moment-style libraries with no tree shaking, polyfills for browsers you no longer support, and duplicated transitive versions. Measure first with a bundle analyser, then code-split by route, lazy-load below-the-fold features, replace heavy libraries, and deduplicate the lockfile. Guessing which import is expensive is almost always wrong.

97. What is the difference between throttling on the client and rate limiting on the server? Senior

Client throttling reduces how often you call, which improves responsiveness and reduces load but is trivially bypassed. Server rate limiting enforces a limit you can rely on, returning 429 with Retry-After. Any client-side limit is a courtesy; the server must assume it is absent.

98. What is the difference between a deep clone via spread and a real deep clone? Fresher

Spread and Object.assign copy only the top level, so nested objects are still shared — mutating obj.a.b affects both copies. structuredClone() does a genuine deep clone including cycles, Maps, Sets and Dates. The spread being "a copy" is one of the most common sources of accidental shared state.

99. What is lazy loading and how do you implement it? 2–5 yrs

Deferring work until it is needed. For images, the loading="lazy" attribute; for code, dynamic import() so a bundle chunk is fetched on demand; for data, fetching on scroll or on route entry. IntersectionObserver is the standard way to detect that something has become visible without a scroll handler.

100. What is the difference between a shallow and a deep comparison in a dependency array? 2–5 yrs

React and similar libraries compare dependencies by reference (===). An object or array literal recreated each render is a new reference, so the effect reruns every time even when the contents are identical. Fix it by memoising the value, depending on primitive fields instead, or using a custom comparator.

101. How would you make a large list render efficiently? Senior

Virtualise it — render only the rows in or near the viewport and translate a spacer to preserve scroll height. Combine with stable keys so the framework can reuse nodes, and avoid recreating handler closures per row. Rendering ten thousand DOM nodes is a layout cost no amount of framework optimisation fixes.

Get these answered live in your real interview

NostrobeAI is a real-time AI interview copilot — it hears the question and drafts a strong answer on your screen, invisible on Zoom, Meet, and Teams. One-time pricing, no subscription.

Try NostrobeAI free