JavaScript Interview Questions: Closures, this, Event Loop and Async Practice
Reviewed by Mark Dickie · Last updated
4 questions on this page you can answer and see marked on the spot. Go to the first one
JavaScript is a dynamically typed, single-threaded language that runs in browsers and on servers through Node.js. Interviewers mostly probe runtime behavior, such as scope and closures, the prototype chain, and the event loop, rather than memorized syntax. Expect to predict the output of short snippets and explain the rule behind it, since most answers turn on hoisting, coercion, or the order of microtasks. Later rounds add ES2015+ features like let and const, classes, modules, and async/await.
Which JavaScript topics do interviewers test first?
| Topic | What the question checks | Typical hands-on prompt |
|---|---|---|
| Closures | Whether a function keeps access to variables from the scope where it was defined | Build a counter factory, then explain why var inside a loop with setTimeout logs the same value each time |
this binding | Rules for call, apply, bind, arrow functions, and extracted methods | Predict this after const f = obj.method; f() in strict mode and in sloppy mode |
| Prototype chain | How property lookup walks __proto__, and how class extends maps onto it | Implement inheritance with Object.create, then rewrite it with class and super |
| Event loop | Order of synchronous code, microtasks, and macrotasks | Predict the log order of setTimeout, Promise.then, and queueMicrotask before running it |
| Type coercion | Results of == versus ===, truthy and falsy values, and + with strings | Explain why [] + {} and [] == ![] evaluate the way they do |
| Hoisting and TDZ | Difference between var, let, const, and function declarations | Explain the ReferenceError raised when a let variable is read before its declaration line |
How should you prepare for a JavaScript interview?
- Predict the output of small snippets on paper, then run them in a console to check your reasoning.
- Write debounce and throttle from scratch, and say where each one calls
setTimeoutand why. - Trace an
async/awaitfunction that awaits a rejected promise, and show where thetry/catchcatches it. - Explain the difference between
requireand ES moduleimport, and why top-levelawaitworks only in ES modules.
Key facts
- Tarmac has 130 JavaScript interview questions on this topic, 10 of them on this page, at difficulty 2–4 of 5.
- Tarmac tracked 2,235 job postings asking for JavaScript in October 2026.
- Roles asking for JavaScript advertise a median base salary of £72,500, across 622 job postings as of October 2026.
- Tarmac last reviewed these JavaScript interview questions on 2 November 2026.
At a glance
| Questions | 10 shown · 130 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
Try one before you open the answer. Pick an option and press Check; it's marked on the spot.
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.
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.
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.
[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.
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.
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.
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".
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.
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.
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
Job market
See javascript salaries and hiring demand from live job postings.
The other 120 questions
This page shows 10 and marks what you pick. That's as far as a page can go. A free account opens the other 120 and keeps every answer. What you miss comes back until it's right: after a day, then at longer gaps.
Free · the whole bank · 100 answers per 30 days, each marked with written feedback