What this round is for
A JavaScript round concentrates on a few areas with surprising reliability: equality and coercion, scope and closures, how this is bound, and the event loop. If you can answer those four well, most of the rest follows.
The questions below are ordered roughly as a round moves - the quick checks first, then the ones about what the engine is doing, then the ones that find out whether you have debugged asynchronous code in anger.
The questions
Answer each one out loud before you open it. An answer you have read is not an answer you can
give under pressure, which is the only kind that counts.
Q1
What is the difference between == and ===?
Show the answer
Hide the answer
== coerces types before comparing; === requires the same type and value.
The coercion rules produce results that cannot be reconciled with any intuitive notion of equality, so the rule is to use === everywhere. The accepted exception is x == null, which catches both null and undefined.
What it is really testing.
Whether you can state the exception. 'Always use ===' is right but incomplete.
Q2
What are the falsy values?
Show the answer
Hide the answer
false, 0, -0, 0n, empty string, null, undefined and NaN.
Everything else is truthy, including '0', 'false', empty arrays and empty objects. An empty array being truthy catches people constantly when checking whether a list has items.
What it is really testing.
Whether you know [] is truthy. It is the one most candidates get wrong.
Q3
What is the difference between null and undefined?
Show the answer
Hide the answer
undefined means a value was never assigned; null means it was deliberately set to nothing.
undefined is what you get from a missing property, an omitted argument or a function with no return. null is a choice somebody made. typeof null returning 'object' is a long-standing bug kept for compatibility.
What it is really testing.
Whether you know typeof null is 'object' and why it has never been fixed.
Q4
What is hoisting?
Show the answer
Hide the answer
Declarations are processed before code runs - var is initialised as undefined, let and const are not.
A var read before its line gives undefined; a let read before its line throws. That gap is the temporal dead zone, and it exists so that using a variable early is an error rather than a silent wrong value.
What it is really testing.
Whether you can name the temporal dead zone and say why it is an improvement.
Q5
What is the difference between var, let and const?
Show the answer
Hide the answer
var is function-scoped and hoisted; let and const are block-scoped with a temporal dead zone.
const prevents reassignment, not mutation - a const array can still be pushed to. The practical rule is const by default, let when you must reassign, var never.
What it is really testing.
Whether you know const does not mean immutable. This catches a surprising number of people.
Q6
What is a closure?
Show the answer
Hide the answer
A function that keeps access to the variables of the scope it was created in, after that scope has returned.
The outer variables are not garbage collected because the inner function still refers to them. This is the mechanism behind private state, memoisation, and every hook in React.
What it is really testing.
Whether you can give a use rather than a definition. A counter or a once-only function is the usual example.
Q7
Why does a loop with var capture the wrong value?
Show the answer
Hide the answer
All iterations share one binding, so by the time the callbacks run the variable holds its final value.
let gives each iteration its own binding, which is why the modern version simply works. Before that the fix was an immediately invoked function to create a fresh scope.
What it is really testing.
Whether you can explain the fix rather than just knowing let works.
Q8
How is this determined?
Show the answer
Hide the answer
By how a function is called, not where it was written.
Called as a method, this is the object. Called bare, it is undefined in strict mode. Called with new, it is the new object. call, apply and bind set it explicitly.
What it is really testing.
Whether you say 'the call site'. That phrase is the whole answer.
Q9
How do arrow functions differ from regular functions?
Show the answer
Hide the answer
They have no this of their own, no arguments object, and cannot be used as constructors.
They take this from the surrounding scope at the point they were written, which is exactly why they fixed the classic callback bug. That also makes them wrong as object methods.
What it is really testing.
Whether you know when NOT to use one. Methods on an object should be regular functions.
Q10
What is the event loop?
Show the answer
Hide the answer
The mechanism that runs queued callbacks when the call stack is empty.
JavaScript is single-threaded, so slow work is handed to the environment and a callback is queued. The stack drains, then all microtasks, then one macrotask, then repeat.
What it is really testing.
Whether you can predict output order. Expect a snippet mixing setTimeout and a promise.
Q11
What is the difference between a microtask and a macrotask?
Show the answer
Hide the answer
Promise callbacks are microtasks and run before the next macrotask, which includes timers.
The whole microtask queue drains after each task, so a promise chain completes before a setTimeout(…, 0) scheduled earlier. That is why the zero timer still runs last.
What it is really testing.
Whether you know microtasks can starve the loop if they keep scheduling more.
Q12
Why does setTimeout with 0 not run immediately?
Show the answer
Hide the answer
Zero means 'as soon as possible after the current work and everything already queued', not 'now'.
The synchronous code must finish, then microtasks drain. Browsers also clamp nested timers to a minimum of about four milliseconds.
What it is really testing.
Whether you understand the queue rather than treating the number as a delay.
Q13
What is a promise?
Show the answer
Hide the answer
An object representing a value that is not available yet, in one of three states.
Once it settles to fulfilled or rejected it never changes again. then and catch register callbacks that run as microtasks when it settles.
What it is really testing.
Whether you know it settles once. A promise is not a stream.
Q14
What problem did promises solve that callbacks did not?
Show the answer
Hide the answer
Error handling. One catch covers a whole chain instead of each callback handling its own failure.
Nesting callbacks meant the failure path was written at every level. A promise chain has a single place for it, and errors propagate down the chain automatically.
What it is really testing.
Whether you name error handling rather than 'callback hell'. Nesting was the symptom.
Q15
What does async/await actually do?
Show the answer
Hide the answer
It is syntax over promises - an async function returns a promise, and await suspends it until one settles.
It does not block the thread. While the function is suspended, other work runs. That is the part people most often get wrong.
What it is really testing.
Whether you know await does not block. The follow-up is what happens to the rest of the program.
Q16
When is awaiting inside a loop a mistake?
Show the answer
Hide the answer
When the operations are independent - it serialises work that could run at once.
Three one-second calls take three seconds in a loop and one second with Promise.all. If each depends on the previous result, the loop is correct.
What it is really testing.
Whether you know when the loop IS right. Blanket answers suggest a memorised rule.
Q17
What is the difference between Promise.all and Promise.allSettled?
Show the answer
Hide the answer
all rejects as soon as any one rejects; allSettled waits for every one and reports each outcome.
all is right when you need everything to succeed. allSettled is right when partial success is acceptable and you want to know which parts failed.
What it is really testing.
Whether you pick based on whether partial success is useful.
Q18
Does fetch reject on a 404?
Show the answer
Hide the answer
No. It only rejects on a network failure - a 404 or 500 resolves with response.ok false.
Code that only has a catch treats a server error as success. Checking response.ok and throwing is the standard pattern, and omitting it is a very common bug.
What it is really testing.
Whether you check response.ok. This is one of the most frequent real defects in fetch code.
Q19
What is the difference between a shallow and a deep copy in JavaScript?
Show the answer
Hide the answer
A shallow copy duplicates the top level and shares nested objects; a deep copy duplicates all the way down.
Spread and Object.assign are shallow. structuredClone does a real deep copy; the old JSON round-trip works but destroys Dates, Maps, Sets, undefined and functions.
What it is really testing.
Whether you know spread is shallow. The bug appears only with nested data.
Q20
Are objects passed by value or by reference?
Show the answer
Hide the answer
The reference is passed by value - so the function can mutate the object but cannot replace it for the caller.
Reassigning the parameter inside the function has no effect outside. Mutating a property does. That distinction explains most 'why did my object change' bugs.
What it is really testing.
Whether you can state it precisely. 'By reference' is the common shorthand and is slightly wrong.
Q21
What is prototypal inheritance?
Show the answer
Hide the answer
Objects delegate to a prototype object, and lookups walk the chain until they find the property or reach null.
class syntax is sugar over this - there are no classes underneath, only objects linked to other objects. Understanding the chain explains how method lookup actually works.
What it is really testing.
Whether you know class is syntax. The follow-up is often what happens when you add to a prototype at run time.
Q22
What is the difference between map, forEach and filter?
Show the answer
Hide the answer
map returns a new array of the same length, filter a subset, forEach returns nothing and is for side effects.
Using map purely for side effects creates an array nobody reads. Using forEach when you wanted a result means building the array by hand.
What it is really testing.
Whether you pick based on the return value rather than habit.
Q23
What does reduce do?
Show the answer
Hide the answer
It collapses an array to a single value by applying a function with an accumulator.
It can express map and filter, and sums, groupings and lookups. A reduce that is hard to read is usually better as a loop - clarity matters more than demonstrating the method.
What it is really testing.
Whether you know when not to use it. A dense reduce is a common readability complaint.
Q24
Why does [10, 9, 1].sort() give [1, 10, 9]?
Show the answer
Hide the answer
sort converts elements to strings by default and compares them lexicographically.
It also mutates the array in place rather than returning a new one. Both surprises catch people, and the fix is passing a comparator.
What it is really testing.
Whether you know it mutates as well. Many candidates know only the string half.
Q25
What is the difference between slice and splice?
Show the answer
Hide the answer
slice returns a copy of a portion and leaves the original alone; splice changes the array in place.
The names are nearly identical and the behaviours are opposite, which is why this question recurs. splice returns the removed elements, not the array.
What it is really testing.
Whether you know which one mutates. The near-identical names are exactly why this is asked.
Q26
What do rest and spread do?
Show the answer
Hide the answer
Spread expands an iterable into its parts; rest gathers remaining items into an array.
They use the same three dots, and which one it is depends on which side of the assignment it appears. Spread is the idiomatic way to copy and merge without mutating.
What it is really testing.
Whether you know the same syntax means opposite things depending on position.
Q27
What is destructuring?
Show the answer
Hide the answer
Pulling values out of objects and arrays by shape, with optional defaults and renaming.
Defaults apply only when the value is undefined, not when it is null - which is a frequent surprise. Destructuring in parameter lists is what makes options objects readable.
What it is really testing.
Whether you know defaults do not apply to null. That trips people with API data.
Q28
What does optional chaining do?
Show the answer
Hide the answer
It short-circuits to undefined when a link in the chain is null or undefined, instead of throwing.
It prevents the most common error message in the language. The caution is that it suppresses an error, and sometimes the error was the useful signal.
What it is really testing.
Whether you know when suppressing the error is wrong. Over-applying it hides real bugs.
Q29
What is the difference between ?? and ||?
Show the answer
Hide the answer
|| falls back on any falsy value; ?? only on null or undefined.
That matters when 0 or an empty string are legitimate values. Using || for a page size silently replaces a valid 0 with the default.
What it is really testing.
Whether you can name a case where || is actively wrong, such as a legitimate zero.
Q30
What are template literals good for?
Show the answer
Hide the answer
Interpolation, multi-line strings, and tagged templates.
Tagged templates let a function process the parts, which is how libraries build safe SQL or styled components. That is the part most candidates have not seen.
What it is really testing.
Whether you have seen tagged templates. Most candidates know only interpolation.
Q31
What is the difference between CommonJS and ES modules?
Show the answer
Hide the answer
CommonJS uses require and executes in place; ES modules use import, are hoisted, static and live.
Static structure is what lets bundlers remove unused exports. Mixing the two produces confusing errors because the semantics differ, not just the syntax.
What it is really testing.
Whether you know why static structure matters for bundling.
Q32
What is event bubbling and how do you use it?
Show the answer
Hide the answer
An event fires on the target then on each ancestor - which lets one listener handle many children.
Delegation attaches a single listener to a container and uses closest to find the item. It works for elements added later, which per-element listeners do not.
What it is really testing.
Whether you reach for delegation. The dynamic-element case is the usual follow-up.
Q33
What is the difference between preventDefault and stopPropagation?
Show the answer
Hide the answer
preventDefault stops the browser's default action; stopPropagation stops the event travelling to ancestors.
Reaching for the second when you meant the first breaks other listeners that had a legitimate reason to run. They are unrelated operations.
What it is really testing.
Whether you know they are unrelated. Using the wrong one breaks other handlers.
Q34
What is the difference between textContent and innerHTML?
Show the answer
Hide the answer
textContent treats the value as text; innerHTML parses it as markup.
Putting user input into innerHTML is a cross-site scripting hole. Defaulting to textContent prevents an entire vulnerability class with no effort.
What it is really testing.
Whether you connect it to security rather than treating it as a style preference.
Q35
What is debouncing and how does it differ from throttling?
Show the answer
Hide the answer
Debounce waits until activity stops; throttle allows one call per interval regardless.
Debounce suits a search box - you want the final value. Throttle suits scroll or resize - you want regular updates while it continues.
What it is really testing.
Whether you can pick the right one for a given interaction.
Q36
What is the difference between localStorage and sessionStorage?
Show the answer
Hide the answer
localStorage persists until cleared; sessionStorage lasts only for the tab.
Both are synchronous and string-only, so large reads block the main thread and objects must be serialised. Neither is appropriate for secrets.
What it is really testing.
Whether you know both are synchronous, and that neither should hold a token.
Q37
What is a generator function?
Show the answer
Hide the answer
A function that can pause and resume, producing a sequence of values on demand.
It is the basis of lazy iteration and was how async flow was managed before async/await. Most code does not need one, but recognising the syntax matters.
What it is really testing.
Whether you recognise the syntax and know what it was used for before async/await.
Q38
How does error handling differ between sync and async code?
Show the answer
Hide the answer
try/catch catches synchronous throws and awaited rejections, but not a promise you never awaited.
An unhandled rejection is one of the most common ways a production bug stays invisible. Either await it or attach a catch.
What it is really testing.
Whether you know the gap. Unhandled rejections are a silent failure mode.
Q39
What is strict mode and what does it change?
Show the answer
Hide the answer
A mode that turns silent failures into errors and removes some legacy behaviour.
Assigning to an undeclared variable throws, this is undefined in a bare function call, and duplicate parameters are rejected. Modules are strict automatically.
What it is really testing.
Whether you know modules are strict by default, so the directive is rarely needed now.
Q40
What is the difference between a WeakMap and a Map?
Show the answer
Hide the answer
A WeakMap holds its keys weakly, so an entry does not stop the key being garbage collected.
It is not enumerable and keys must be objects. The use case is attaching data to an object without preventing it from being freed - metadata and private fields.
What it is really testing.
Whether you can name a real use. Most candidates know it exists and not why.