# 30 technical interview questions, explained the way you'd actually say them

> Source: <https://dev.to/ramana_babu_c787073206bef/30-technical-interview-questions-explained-the-way-youd-actually-say-them-4a3g>
> Published: 2026-08-03 03:05:35+00:00

Most interview prep content gives you a definition. Real interviews test

something different: can you explain your reasoning clearly, out loud,

under a little pressure — not just recite the right words.

I put together 30 questions across JavaScript, React, and Node.js. Every

answer here is written the way you'd actually say it in an interview, not

the way a textbook would write it.

**How to actually use this:** cover the answer, try explaining it out

loud in under 30 seconds, *then* read the answer. If you froze or

rambled, that's the real signal — more than whether you technically knew

the concept.

A closure is a function that remembers the variables from where it was

created, even after that outer function has finished running. It powers

private variables, debouncing, memoization, and module patterns.

`setTimeout(fn, 0)`

vs `Promise.then()`

— which runs first?
The Promise wins. `.then()`

callbacks go into the microtask queue, which

fully drains before the next macrotask (like `setTimeout`

) runs — even

with a 0ms delay.

`var`

break inside loops with closures, but `let`

doesn't?
`var`

is function-scoped — every iteration shares the same variable.

`let`

is block-scoped, so each iteration gets its own fresh binding.

`==`

actually give you a different (and wrong) answer than `===`

?
`==`

does type coercion first — `0 == false`

and `'' == 0`

are both

true. `===`

compares type and value directly, no surprises.

`this`

break in callbacks with regular functions, but not arrow functions?
Regular functions get `this`

based on how they're called. Arrow

functions inherit `this`

lexically from where they were defined, so it

stays consistent no matter how they're invoked.

JS walks the prototype chain — the object, then its prototype, then

that prototype's prototype — until it's found or it hits `null`

.

Search wants **debounce** — fire once after typing stops. Scroll wants

**throttle** — fire at a steady max rate continuously.

`Promise.all`

vs `Promise.race`

?
Use `all`

when you need every result, and it should reject if any fail.

Use `race`

when you only care about whichever resolves first.

Function declarations fully hoist. `const fn = () => {}`

only hoists

the declaration, not the assignment, so calling it early throws.

Currying transforms `f(a,b,c)`

into `f(a)(b)(c)`

. It's useful for

creating reusable, partially-configured functions.

React batches changes, diffs the old and new virtual trees, and only

touches the specific real DOM nodes that actually changed.

`useEffect`

completely?
The effect runs after every single render — a common source of

infinite loops if the effect itself updates state.

`setState`

3 times in one event handler — does React re-render 3 times?
No. React batches updates within the same handler into a single

re-render, and React 18 extends this batching further.

`key`

break things when a list reorders?
React matches elements between renders by `key`

. Using the index means

React thinks the item *at that position* changed, not that it moved.

A controlled input's value lives in React state and updates via

`onChange`

. An uncontrolled input's value is managed by the DOM itself,

read via a `ref`

when needed.

`useMemo`

vs. `useCallback`

— what's the actual difference in what gets memoized?
`useMemo`

memoizes a computed value. `useCallback`

memoizes the

function itself — useful for stable references passed to memoized

children.

Context re-renders every consumer on any value change — bad for

frequently-changing state. It's best for rarely-changing global data

like theme or auth.

`React.memo`

, but it's still re-rendering every time. Why?
`React.memo`

does a shallow prop comparison. A new object, array, or

function reference each render looks different even if the underlying

data is the same.

A function whose name starts with `use`

and that calls other hooks

inside it. The naming convention is how React's linter enforces the

rules of hooks.

`try/catch`

work for catching rendering errors in React?
`try/catch`

only catches synchronous errors in code you directly run.

Error Boundaries hook into React's own lifecycle to catch errors during

rendering.

JavaScript execution is single-threaded, but I/O operations get

delegated to a thread pool. The event loop picks up completed I/O and

runs the callbacks, never blocking on the wait.

Reading the whole file into memory holds it all in RAM per request.

Streams process and send data in small chunks, keeping memory usage

flat regardless of file size.

`next()`

actually do in Express middleware, and what breaks if you forget it?
It passes control to the next handler in the chain. Forget it, and the

request just hangs forever with no response ever sent.

Not easily. JWTs are stateless, so you'd need extra infrastructure like

a blocklist or short expiry with refresh tokens to revoke one early.

It lets asynchronous code read top-to-bottom like synchronous code,

with normal `try/catch`

for errors — much easier to reason about than

chained callbacks.

The `cluster`

module forks multiple copies of the process across

cores, sharing the same port, so incoming requests get distributed

across the workers.

`.env`

file to Git a serious mistake, not just messy?
It usually holds real secrets. Once committed, it's in the Git history

permanently — deleting the file later doesn't remove the old commits.

`GET`

to delete a resource, even if it technically works?
`GET`

is supposed to be safe and idempotent. Browsers and crawlers can

pre-fetch `GET`

URLs, which could accidentally trigger a deletion.

Express checks a function's parameter count to identify it as an error

handler. A 4-argument signature is specifically what signals that role.

`package.json`

, same `npm install`

— can two people end up with different dependency versions?
Yes, without a `package-lock.json`

. Version ranges can resolve

differently over time, and the lockfile pins exact versions for

reproducible installs.

Reading an answer and being able to say it clearly under pressure are

two different skills. I've been building [Sparlog](https://sparlog.com)

— an AI that actually interviews you: you explain your reasoning out

loud while writing code, and it scores clarity and correctness

together, the way a real interviewer would.

It's free to try, currently in open beta. Would genuinely love feedback

if you give it a shot.

Also made a free downloadable PDF version of this list if you'd rather

have it offline: [sparlog.com/resources](https://sparlog.com/resources)
