JavaScript interview questions
Reviewed by Mark Dickie · Last updated
JavaScript is a single-threaded, dynamically typed language that runs in browsers and on servers via Node.js. For interview prep, the topics that come up most are closures, the event loop, prototypes and this binding, async patterns (callbacks, promises, async/await), and the quirky coercion rules that produce unexpected results at runtime. You should also be comfortable with ES6+ syntax (destructuring, spread/rest, modules, arrow functions) and the difference between value and reference semantics for primitives versus objects.
| Topic | What to know cold | Common interview angle |
|---|---|---|
| Closures | Inner functions retain access to outer scope after the outer function returns | Write a counter or explain why a loop with var + setTimeout prints the wrong numbers |
| Event loop | Call stack, microtask queue, macrotask queue, and execution order | Predict output of mixed setTimeout and Promise.then calls |
Prototypes / this | __proto__, prototype on functions, Object.create, new, explicit/implicit/default binding | Reimplement a simple class with constructor + shared method using only prototypes |
| Async | Promise states, chaining, error propagation, async/await desugaring | Explain why await in a loop serialises requests and how Promise.all fixes it |
| Coercion | == vs ===, ToPrimitive, ToNumber, ToString, NaN checks | Given 5 expressions, predict each result and explain the abstract operation invoked |
| Value vs reference | Primitives copy on assignment; objects share the reference | Trace mutations through a function that reassigns vs mutates an argument |
What does a JavaScript interview actually test?
Interviewers are checking whether you can reason about execution order, scope, and types without running the code. Most whiteboard or live-coding rounds include at least one "predict the output" snippet and one small implementation task.
- Read code and predict output. You will see snippets mixing
console.log, promises,setTimeout, and variable declarations. Knowing the exact order of microtask vs macrotask resolution is the make-or-break skill here. - Implement something from scratch. Common asks:
debounce,throttle,deepClone, a simplePromise.all, or a polyfill forbindorObject.create. - Explain a concept out loud. "What is a closure?" or "How does
thiswork?" are still asked. A clear two-sentence answer with a concrete example beats a textbook paragraph. - Debug or trace a bug. You may be handed code with a subtle reference-copy bug or a race condition and asked to find and fix it.
How should I prepare if I have limited time?
Prioritise the event loop and closures first. They appear in nearly every JavaScript round and they are the topics where candidates most often stumble under pressure. Spend remaining time on prototype chains and async error handling, since those tend to separate mid-level from senior candidates.
Key facts
- Tarmac has 114 JavaScript interview questions on this topic, 10 of them on this page, at difficulty 2–4 of 5.
- Tarmac last reviewed these JavaScript interview questions on 18 August 2026.
At a glance
| Questions | 10 shown · 114 in the bank |
|---|---|
| Difficulty | 2–4 of 5 |
| Formats | Multiple choice, True / false, Find the bug, Fill in the blank, Coding exercise, Multiple answer, Code output, Short answer, Flashcard, Ordering |
| Interactive | 1 run your code against tests, in the app |
What you'll review
- primitive types
- var let const
- array methods
- destructuring
- type coercion
- closures
- this rules
- promise ordering
Practice questions
JavaScript/types-coercion/primitive-types
What does typeof null evaluate to?#
Options
Show answer
typeof null evaluates to the string object. This is a long-standing bug from the very first JavaScript implementation that has been kept for backward compatibility, so null reports as type object despite being a primitive. To reliably test for null, compare directly with value === null.
typeof null returns "object" — a long-standing bug from the first JS implementation that is kept for backward compatibility. Use value === null to test for null.
JavaScript/scope-closures/var-let-const
Declaring an object with const makes the object immutable.#
Options
Show answer
False. const only prevents reassigning the binding itself — the object it points to can still have its properties added, changed, or deleted. If you need the contents to be immutable, use Object.freeze for a shallow freeze of the object's own properties.
const only prevents reassigning the binding. The object it points to can still have its properties changed. Use Object.freeze for shallow immutability.
JavaScript/arrays/array-methods
This function should sum an array but returns NaN. Which line has the bug?#
function sum(arr) {
let total = 0;
for (let i = 0; i <= arr.length; i++) {
total += arr[i];
}
return total;
}Show answer
The bug is on line 3.
i <= arr.length reads one index past the end. arr[arr.length] is undefined, and total + undefined is NaN. The condition should be i < arr.length.
JavaScript/arrays/array-methods
[1, 2, 3]._____(n => n * 2) returns a new doubled array, while [3, 1, 2]._____() reorders the array in place.#
Show answer
[1, 2, 3].**map**(n => n * 2) returns a new doubled array, while [3, 1, 2].**sort**() reorders the array in place.
map returns a new array of transformed elements without mutating the original; sort mutates the array in place (and returns it). Mixing the two up is a classic source of accidental mutation bugs.
JavaScript/objects/destructuring
Implement parseQueryString(query): parse a URL query string like "a=1&b=hello%20world&c" into a plain object. Values are percent-decoded with decodeURIComponent; a key with no = gets the empty string; an empty input returns {}.#
Starter code
function parseQueryString(query) {
// TODO: split on & and =, decode values
return {};
}Your solution must pass
- two plain pairs
- percent-encoded value
This one is written and run, not read. Solve it in the app and your code is executed against these tests and the hidden ones.
JavaScript/types-coercion/type-coercion
Which of these values are falsy in JavaScript?#
Options
Pick every one that applies.
Show answer
The falsy values here are 0 and NaN. JavaScript's complete falsy set is false, 0, -0, 0n, the empty string, null, undefined, and NaN. The string '0' is a non-empty string and an empty array [] is an object, so both of those are truthy.
The falsy values are false, 0, -0, 0n, '', null, undefined, and NaN. The string '0' and an empty array [] are both objects/non-empty strings and are truthy.
JavaScript/types-coercion/primitive-types
What does this log?#
console.log(typeof typeof 1);Show answer
string
typeof 1 is the string "number", and typeof "number" is "string". typeof always produces a string, so applying it twice always yields "string".
JavaScript/scope-closures/closures
What is a closure, and give one practical use for it.#
Show answer
A closure is a function bundled together with references to its surrounding lexical scope, so it can keep accessing those variables even after the outer function has returned. A common use is data privacy — e.g. a counter factory that keeps count private and exposes only an increment function.
Closures capture variables by reference from the scope in which a function was defined. They power module patterns, data privacy, partial application, and stable callbacks.
JavaScript/this-binding/this-rules
In strict mode, what is this inside a regular function called as a standalone function (e.g. fn())?#
Show answer
undefined. In strict mode this is not coerced to the global object, so a plain function call leaves it undefined.
Outside strict mode the same call would set this to the global object (window/globalThis). Arrow functions ignore call-site this entirely and use the enclosing scope's.
JavaScript/event-loop/promise-ordering
This runs top to bottom:#
Put these in order
Show answer
Synchronous code runs first, then microtasks drain before any macrotask, so the order is:
ADCB
A and D are synchronous. The resolved promise's .then (C) is a microtask that drains before the next macrotask, so it runs ahead of the setTimeout callback B, which is a macrotask.
Synchronous code runs first (A, then D). Microtasks (the resolved promise's .then, C) drain before the next macrotask, so C precedes the setTimeout callback B, which is a macrotask.
Sources
The official documentation these questions are checked against:
Related interview questions
The other 104 questions
This page shows 10. A free account opens the rest and marks your answers, which a page of answers can't do. Miss one and it returns a few days later, then a week after that, until you stop missing it.
Free · the whole bank · 100 graded answers per 30 days · written feedback and job-ad quizzes on the paid plan