The questions that come up most often, each with a sample answer you can adapt into your own words. Read them out loud until the explanation feels natural.
What is a closure?
FundamentalsA closure is a function bundled together with references to the variables from the scope in which it was created. It lets an inner function keep accessing those outer variables even after the outer function has returned. Closures power data privacy (module patterns), function factories, and stateful callbacks; the classic gotcha is capturing a loop variable, which let fixes by giving each iteration its own binding.
Explain the difference between == and ===.
Fundamentals=== is strict equality: it compares value and type with no coercion. == is loose equality: it coerces operands to a common type before comparing, which produces surprising results like 0 == '' being true and null == undefined being true. The practical rule is to always use === unless you specifically want the null == undefined check.
How does the event loop work?
AdvancedJavaScript runs on a single thread with a call stack. When the stack is empty, the event loop pulls the next callback to run. Microtasks (Promise callbacks, queueMicrotask) are drained completely after each task and before the next macrotask (setTimeout, I/O callbacks). That ordering is why a resolved Promise's .then runs before a setTimeout(0) scheduled at the same time.
What is the difference between var, let, and const?
Fundamentalsvar is function-scoped and hoisted with an initial value of undefined, which causes leakage out of blocks. let and const are block-scoped and live in a temporal dead zone until declared, so referencing them early throws. const additionally forbids reassignment of the binding (though the referenced object can still be mutated). Modern code uses const by default and let when reassignment is needed.
How is the value of this determined?
Intermediatethis is bound at call time, not definition time. In a plain function call it is undefined in strict mode (or the global object otherwise); as a method it is the object before the dot; with new it is the new instance; and with call/apply/bind it is whatever you pass. Arrow functions are the exception: they capture this lexically from the enclosing scope, which is why they are preferred for callbacks that need the outer this.
What is the difference between a Promise and a callback?
IntermediateA callback is a function passed to an async operation to run on completion; nesting many of them produces 'callback hell' and makes error handling awkward. A Promise is an object representing a future value with .then/.catch chaining and a single, composable error path. async/await is syntactic sugar over Promises that lets you write asynchronous code in a synchronous-looking style with normal try/catch.
What does the spread operator do, and how does it differ from rest?
IntermediateThey share the ... syntax but do opposite things by context. Spread expands an iterable into individual elements: [...arr], {...obj}, or fn(...args), commonly used for shallow copies and merges. Rest collects the remaining items into an array or object: function f(...args) or const [first, ...rest] = arr. Spread unpacks; rest gathers.
Why should you never block the event loop in Node.js?
AdvancedNode handles many concurrent connections on a single thread by never blocking; while the thread is busy, no other request, timer, or I/O callback can run. A synchronous CPU-heavy operation (a large JSON.parse, a tight crypto loop) freezes every client until it finishes. The fixes are to offload heavy work to worker threads or a separate process, stream large payloads, and use the async APIs.
What is debouncing and how would you implement it?
IntermediateDebouncing delays a function until a burst of calls has gone quiet: each new call resets a timer, and the function runs only after a pause. It is the standard fix for expensive handlers on chatty events like keystrokes in a search box or window resizing. The implementation is a closure holding a timer id, which is why this question doubles as a closure check. The sibling technique, throttling, runs at most once per interval instead of waiting for silence; knowing which fits which case is the senior detail.
function debounce(fn, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
input.addEventListener("input", debounce(search, 300));
What does Array.prototype.reduce do?
Intermediatereduce folds an array into a single value by running a callback against an accumulator for each element, starting from an initial value. It generalises map and filter: anything you can compute by walking an array once can be expressed as a reduce, from sums to grouping objects by a key. The common mistakes are omitting the initial value (the first element becomes the accumulator, which breaks on empty arrays) and reaching for reduce where map or a plain loop is clearer. Readability is part of the answer interviewers want to hear.
const orders = [
{ customer: "a", total: 20 },
{ customer: "b", total: 35 },
{ customer: "a", total: 15 },
];
const byCustomer = orders.reduce((acc, o) => {
acc[o.customer] = (acc[o.customer] ?? 0) + o.total;
return acc;
}, {});
What is hoisting?
FundamentalsHoisting is the way declarations are processed before code runs. Function declarations are hoisted with their bodies, so you can call them above where they appear. var declarations are hoisted but initialised to undefined, which is why reading one early gives undefined rather than an error. let and const are also registered up front but stay in the temporal dead zone until their declaration line, so touching them early throws. The interview point is predicting output for a snippet mixing all three, not reciting the definition.
How does prototypal inheritance work?
AdvancedEvery object has an internal link to a prototype object. When you read a property the object itself lacks, the engine walks up the prototype chain until it finds the property or reaches null. Methods live once on the prototype and are shared by every instance, which is what class syntax sets up under the hood: class methods land on ClassName.prototype. Object.create builds an object with a chosen prototype directly. Being able to say that class is syntax over prototypes, not a new object system, is the distinction interviewers listen for.