Programming Languages

JavaScript interview questions

Closures, the event loop, prototypes, and async behavior are what interviewers probe for JavaScript, testing whether you understand how the language actually executes rather than just its syntax. Expect follow-ups that push on edge cases like hoisting, `this` binding, and coercion.

6 questions (1 easy · 3 medium · 2 hard), each with what a strong answer covers and where people lose the point. Free to read, no account.

On this page (6 questions)

1.What is the difference between var, let, and const, and what is the temporal dead zone?

Warm-up

What a strong answer covers

  • var is function-scoped and hoisted with an initial value of undefined; let and const are block-scoped ({ } bounded).
  • let and const are hoisted too but not initialized, so accessing them before their declaration throws a ReferenceError. That gap is the temporal dead zone.
  • const forbids reassignment of the binding, but the value can still be mutated (a const object's properties can change); it is not deep immutability.
  • Practical guidance: default to const, use let when reassignment is needed, avoid var in new code.

Where people lose the point

  • Claiming let and const are not hoisted at all, rather than hoisted-but-uninitialized.
  • Saying const makes an object immutable instead of just preventing rebinding.
  • Confusing block scope with function scope, e.g. expecting a var inside an if to be block-local.
Link to this question

2.Explain closures. Give a concrete example where one is useful, and describe the classic loop bug.

Core

What a strong answer covers

  • A closure is a function bundled with references to the lexical scope in which it was defined, so it retains access to those variables even after the outer function returns.
  • Useful cases: data privacy / module pattern (a counter with a private count), partial application / currying, and memoization caches.
  • Classic bug: a for loop with var capturing the same shared binding, so all callbacks log the final value. Fixing it with let gives each iteration its own binding.
  • Notes that closures keep referenced variables alive in memory, which can cause leaks if long-lived closures capture large objects.

Where people lose the point

  • Describing a closure as just a nested function, missing that it captures and retains its enclosing scope.
  • Not being able to explain why var breaks the loop while let fixes it (shared vs per-iteration binding).
  • Overlooking the memory implication that captured variables cannot be garbage collected while the closure lives.
Link to this question

3.How is the value of `this` determined in JavaScript, and how do arrow functions differ?

Core

What a strong answer covers

  • For regular functions `this` is set by the call site: method call binds to the object before the dot, plain call is undefined in strict mode (or the global object otherwise), new binds to the fresh instance.
  • call, apply, and bind explicitly set `this`; bind returns a permanently bound copy.
  • Arrow functions have no own `this`; they capture `this` lexically from the enclosing scope, which is why they are ideal for callbacks inside methods.
  • A strong answer names the precedence order: new > explicit bind/call/apply > implicit method call > default.

Where people lose the point

  • Saying `this` is determined by where a function is defined rather than how it is called (true only for arrow functions).
  • Using an arrow function as an object method and expecting `this` to point at the object.
  • Forgetting that a detached method (const f = obj.method) loses its implicit binding when called alone.
Link to this question

4.Predict the output order of a script mixing synchronous code, setTimeout, and a resolved Promise. Explain why.

Hard

What a strong answer covers

  • JavaScript is single-threaded with a call stack; the event loop runs queued work only when the stack is empty.
  • Synchronous code runs first. Then the microtask queue (Promise .then/.catch, queueMicrotask, await continuations) is fully drained before any macrotask.
  • setTimeout/setInterval callbacks are macrotasks and run after all pending microtasks, so a resolved Promise's .then fires before a setTimeout(0).
  • The loop drains all microtasks after each macrotask, so a correct trace is: sync -> microtasks -> one macrotask -> its microtasks -> next macrotask.

Where people lose the point

  • Treating setTimeout(fn, 0) as immediate and ordering it before Promise callbacks.
  • Not distinguishing the microtask queue from the macrotask queue at all.
  • Forgetting that await pauses the async function and schedules the rest as a microtask, changing ordering.
Link to this question

5.How do you run several async operations in parallel and handle partial failure? Contrast Promise.all with Promise.allSettled.

Hard

What a strong answer covers

  • Kick off the promises before awaiting so they run concurrently, then await the combinator, rather than awaiting each in sequence.
  • Promise.all resolves with an array of results once all succeed, but rejects immediately on the first rejection (fail-fast), discarding the other results.
  • Promise.allSettled always resolves with a status/value-or-reason object per promise, so you can inspect partial success; use it when one failure should not sink the batch.
  • Mentions Promise.race and Promise.any, and that async/await is syntactic sugar over promises so try/catch wraps awaited rejections.

Where people lose the point

  • Awaiting promises one at a time in a loop and calling it parallel, when it is actually sequential.
  • Reaching for Promise.all when partial failure must be tolerated (allSettled is the right tool).
  • Forgetting that a rejected promise without a catch produces an unhandled rejection.
Link to this question

6.Explain prototypal inheritance and the prototype chain. How does it relate to ES6 class syntax?

Core

What a strong answer covers

  • Every object has an internal link to a prototype object; property lookups walk this chain until found or until it reaches null.
  • A function's prototype property becomes the [[Prototype]] of instances created with new, so shared methods live once on the prototype rather than per instance.
  • ES6 class is syntactic sugar over this: methods go on Class.prototype, extends sets up the chain, and super calls the parent constructor.
  • Distinguishes own properties from inherited ones (hasOwnProperty) and knows Object.create makes a new object with a chosen prototype.

Where people lose the point

  • Believing JavaScript classes introduce classical inheritance rather than wrapping prototypes.
  • Confusing the instance-facing __proto__ / [[Prototype]] with the function's prototype property.
  • Assuming inherited properties show up as own properties, breaking for...in or hasOwnProperty reasoning.
Link to this question
No account needed

Answer one real JavaScript question now

A question a JavaScript panel actually asks, answered out loud, scored on what you said and how you said it. Under two minutes, and nothing to sign up for.

What is the difference between var, let, and const, and what is the temporal dead zone?

We never store the audio. Your answer is deleted within 24 hours unless you save the result.

How JavaScript answers get judged

The weights a JavaScript interviewer is holding, whether or not they say so out loud. Round Zero scores your practice answers against exactly these, and quotes your own words back as the evidence for each.

Mental model of the runtime

40%

Explains how JavaScript actually executes: the single-threaded event loop, call stack, closures over lexical scope, prototype chain, and how async work is scheduled rather than blocking.

Correctness on edge cases

35%

Gets the tricky details right: hoisting and the temporal dead zone, dynamic `this` binding, coercion rules, microtask vs macrotask ordering, and reference vs value semantics.

Communication and reasoning

25%

Traces execution step by step, predicts output before running it, states assumptions, and reaches for the idiomatic modern tool (const/let, async/await, array methods) with a reason.

Role tracks that include JavaScript

Related Programming Languages skills

All skills →

Now say them out loud

You have read what strong JavaScript answers contain. The next thing that moves the needle is producing one under time, out loud, and finding out where it falls apart.

  • These questions asked back, with follow-ups
  • Flashcards for the ones you keep missing
  • A scored mock that quotes your own answers

Browse every skill

Practising JavaScript: common questions

What JavaScript interview questions should I practice?
Start with the core areas JavaScript interviewers probe: What is the difference between var, let, and const, and what is the temporal dead zone; Explain closures. Give a concrete example where one is useful, and describe the classic loop bug.; How is the value of `this` determined in JavaScript, and how do arrow functions differ. This page outlines strong answers and common mistakes, and the scored path drills each one with follow-ups.
Is the JavaScript practice free?
Yes. The JavaScript path runs free inside Round Zero: lessons, practice questions and flashcards. Drills are unlimited on every plan, free included. So is the full scorecard. Free also covers 3 complete scored interviews, no card.
How is this different from a JavaScript question list?
A static list gives you questions with no feedback. Round Zero runs a live scored practice that probes your actual answers, rotates difficulty, and tells you exactly what to fix, grounded in a JavaScript rubric.
How should I prepare for a JavaScript interview?
Learn the concepts, drill the questions until answers come fast, then prove it in a scored mock. Round Zero sequences all three so you know you are ready, not just that you read about JavaScript.
How is a JavaScript answer scored?
JavaScript answers are scored on mental model of the runtime, correctness on edge cases, communication and reasoning, with evidence quoted from what you actually said, so feedback is specific instead of generic praise.