The JavaScript questions I ask in a frontend interview
The JavaScript questions I ask in frontend interviews, from stale closures and the event loop to async races, and what a good answer sounds like.
JavaScript questions in a frontend interview have a reputation for being trivia. Trick questions about this, puzzles about what gets logged in which order, obscure corners of type coercion. I do not ask those for their own sake. I ask JavaScript questions because almost every frontend bug I have shipped or fixed came down to one of a handful of ideas, and I want to know you can reason about them when the code is real and the deadline is close.
I am Harry Ashton. I built CodePrepped so engineers stop guessing what hiring managers look for. This post continues the series with the CSS questions I ask, the accessibility questions I ask and the performance questions I ask.
Photo: Nemuel Sereti / Pexels.
What I am actually testing
I am not checking whether you have memorised the specification. I am checking three things: can you predict what code will do before you run it, can you explain why when it surprises you, and do you know when the language is the wrong place to be clever. Most of my questions start with a short snippet from a real codebase, slightly simplified, and a question about what happens.
"Why does this show the old value?"
I show a small component or event handler that reads a variable inside a callback, and the callback sees a stale value. This is my closures question, though I rarely use the word. Strong answers explain that the function captured the variable from the scope where it was created, and then talk about how to fix it: read the latest value at call time, pass it in, or in React terms, fix the dependency list or use a ref deliberately.
The weaker answer is "add it to the dependency array" with no idea why. That works until it causes an infinite loop, and then you are stuck. I want the mental model, not the incantation.
"In what order do these lines run?"
Yes, I ask an event loop question. But I keep it grounded. Usually it is a function that logs something, awaits a fetch, sets a timeout and resolves a promise, and I ask what the user sees and when. I want to hear that synchronous code runs first, promise callbacks run before timer callbacks, and that await pauses the function, not the whole page.
The follow-up is the useful part: why does the page freeze when someone runs a big loop over a few thousand items on click? If you can connect the event loop to a janky interface and suggest breaking the work up or moving it off the main thread, that is the answer I am hoping for.
"What happens if this request fails, or two of them race?"
This is my async error handling question, and it separates people who have shipped real features from people who have only done tutorials. A search box fires a request on every keystroke. The responses come back out of order. Sometimes one fails. What does the user see?
Good answers mention catching errors close to where you can do something useful with them, showing the user a sensible state, and cancelling or ignoring outdated requests with an AbortController or a simple "is this still the latest request" check. Bonus points for mentioning debouncing, and for asking what the product wants to happen rather than assuming.
"Why did changing this object change that one too?"
References trip up a lot of people, and they cause some of the most confusing bugs in state management. I show code that copies an object with the spread operator, changes a nested property, and accidentally changes the original as well.
I want to hear the difference between a shallow and a deep copy, why frameworks that compare by reference miss changes when you mutate in place, and what you would do about it. Knowing that structuredClone exists is useful. Knowing that you often do not need a deep copy at all, and can just copy the path you are changing, is more useful.
"What is this here?"
I do ask it, but only in one context: a method passed as a callback that suddenly loses access to its object. I want you to explain that regular functions get this from how they are called, arrow functions take it from where they are written, and that this is why passing obj.method into an event listener can break. If you have written mostly modern React and rarely hit this, say so. Being able to reason it out on the spot is fine.
"How would you make this easier to change?"
This is the senior question. I show a function that has grown too big: it fetches data, transforms it, handles errors and updates the page all in one place. I ask how you would restructure it.
I am listening for separating pure logic from side effects so the logic can be tested, naming things after what they mean rather than what they do internally, and knowing when to stop. Splitting a forty line function into twelve files is not an improvement. If you mention TypeScript and how types would have caught a bug in the snippet, that is welcome too, as long as you can explain what the type is protecting against.
Answers that make me write a careful note
- Guessing the output of a snippet without reasoning out loud.
- Wrapping everything in
tryandcatchand logging the error, with nothing shown to the user. - Fixing a stale value bug by disabling the linter warning.
- Not being able to explain a line of your own take-home code.
None of these end an interview on their own. They are prompts for a follow-up, and "I would not write it that way now, here is why" is a perfectly good recovery.
How to prepare
Skip the lists of a hundred trick questions. Instead, take a feature you have built and write down every bug it ever had. For each one, write a sentence about which JavaScript idea caused it: a closure, a race, a mutation, an unhandled rejection. Those stories are what I want to hear, and they are far easier to remember under pressure than definitions.
Then practise explaining them out loud. CodePrepped's mock interviews and AI Trainer let you rehearse follow-ups like "why did that fix work?" before someone like me asks. If you are applying now, the shortlist scorecard shows what to work on before your next screen.
Do I need to know the event loop in detail?
You need the basics: synchronous code first, then promise callbacks, then timers, and that long synchronous work blocks the page. I do not expect you to name every queue in the specification.
Will I be asked to write JavaScript without a framework?
Sometimes. A small exercise like debouncing a function or fetching and rendering a list in plain JavaScript shows whether you understand what the framework is doing for you. Talk through your thinking as you go.
Is TypeScript expected?
For most roles I hire for, yes, but I care more that you understand the JavaScript underneath. Types describe the shape of your data. They do not change how closures, promises or references behave.
What if I freeze on an output question?
Slow down and walk through it line by line out loud. Getting the order slightly wrong with clear reasoning tells me more than a confident correct guess.
