JavaScript Interview Questions

JavaScript interview questions: closures, hoisting, prototypes, this, promises, async/await and ES6.

29 questions

1 What is the difference between let, const and var? EASY
  • var - function scoped, hoisted (initialised to undefined), can be redeclared and reassigned. Avoid it in modern code.
  • let - block scoped, hoisted but not initialised (temporal dead zone), can be reassigned.
  • const - block scoped like let but the binding cannot be reassigned; object contents can still change.

Prefer const by default, let when you must reassign, and never var.

2 Explain closures with an example. MEDIUM

A closure is a function that remembers variables from the scope where it was created, even after that scope has exited.

function counter() {
  let count = 0;
  return function () {
    count += 1;
    return count;
  };
}
const c = counter();
c(); // 1
c(); // 2

Here the inner function closes over count, keeping it alive. Closures power module patterns, callbacks and private state.

3 What is the event loop and how do promises fit in? HARD

JavaScript runs on a single thread. Long tasks block the thread, so async work (timers, network, I/O) is delegated: the callback is queued and the event loop picks it up when the call stack is empty.

Promises schedule their reactions as microtasks, which run after the current task and before the next macrotask (setTimeout). So Promise.then callbacks fire before pending timer callbacks. async/await is just syntactic sugar over promises.

4 What is the difference between == and ===? EASY

== compares after type coercion (e.g. 1 == "1" is true), which hides bugs.

=== compares value and type without coercion (1 === "1" is false). Always prefer strict equality; use null checks via x == null only when you deliberately accept both null and undefined.

5 What are arrow functions and how do they differ from function declarations? MEDIUM

Arrow functions (const f = (x) => x * 2) have a shorter syntax and - most importantly - no own this: they inherit this lexically from the enclosing scope, and they cannot be used as constructors.

Regular functions have their own this (dynamic based on invocation) and can be called with new. Choose the right tool: methods and constructors use regular functions; callbacks and short transformers fit arrows.

6 What is the DOM and what does document.querySelector do? EASY

The DOM (Document Object Model) is the tree representation of the page that JavaScript can read and modify: elements, attributes and text are nodes.

document.querySelector(selector) returns the first element matching a CSS selector (".btn", "#id", "div > p"); querySelectorAll returns a static NodeList. Then you can change classes, styles, text or attach event listeners.

7 What is the difference between null and undefined? EASY

undefined means a variable has been declared but has no value yet - the engine assigns it as the default. null is an intentional assignment representing "no value". Checks: typeof null === "object" (a historical quirk), typeof undefined === "undefined". Use x == null to catch both, or ?? for defaults (nullish coalescing).

8 What are the different types of data in JavaScript? EASY

Primitives: string, number, boolean, null, undefined, symbol (ES6) and bigint. Non-primitive: object (which includes arrays and functions). Primitives are immutable and compared by value; objects are compared by reference.

9 What is hoisting? MEDIUM

Hoisting moves var declarations and function declarations to the top of their scope at compile time. So a function declared with function keyword can be called before its text; a var is defined as undefined before assignment. let/const are hoisted but stay in the temporal dead zone until the declaration line runs, so using them early throws ReferenceError.

10 What is the difference between var, let and const? MEDIUM

var is function-scoped, hoisted as undefined and re-declarable - it also leaks into the global scope. let is block-scoped, cannot be redeclared in the same scope and is not usable before its declaration. const is like let but the binding is read-only - the value cannot be reassigned (though objects/arrays it points to can still be mutated). Prefer const, then let; avoid var.

11 What is a closure and give a typical use? MEDIUM

A closure is a function that remembers the variables from the scope in which it was created, even after that scope exits:

function counter() {
  let n = 0;
  return () => ++n;
}
const c = counter();
c(); // 1
c(); // 2

Uses: data privacy, factory functions, event handlers and partial application / currying.

12 What is the difference between let and const inside a loop? MEDIUM

Each loop iteration with let creates a fresh binding for the variable, so closures created inside the loop capture the correct per-iteration value. With var the same binding is shared, so all closures see the final value. The classic fix for the var bug was an IIFE; now let solves it directly, and for-of also creates per-iteration bindings.

13 What is the difference between an arrow function and a regular function? MEDIUM

Arrow functions: no own this (they inherit lexically from the surrounding scope), no arguments object, cannot be used as constructors with new, no prototype, and concise syntax. Regular functions have their own dynamic this (based on how they are called). Use arrows for callbacks and small transforms; use functions/methods when you need this or arguments.

14 What is the difference between call(), apply() and bind()? MEDIUM
  • fn.call(ctx, a, b) - invoke fn immediately with a given this and arguments listed.
  • fn.apply(ctx, [a, b]) - same, but arguments in an array.
  • fn.bind(ctx, a) - returns a new function with this permanently bound (and optional partial args); invoke it later.

bind is great for event handlers where this must stay fixed.

15 How does the prototype chain and prototypal inheritance work? MEDIUM

Every object has a hidden __proto__ (the prototype) that is another object. Property lookup walks up this chain until a match or null - that is why almost everything can reach Object.prototype methods. Classes (ES6) are syntactic sugar over prototypes:

class Dog extends Animal {}
// Dog.prototype inherits from Animal.prototype

This is prototype-based inheritance under the hood.

16 What is the difference between Object.create, the new keyword and es6 classes? HARD

new F() creates an object, sets its prototype to F.prototype and runs F with this set to it. Object.create(p) creates an object whose prototype is exactly p - clean, explicit inheritance and prototype reuse. ES6 class/extends is a clearer syntax for the same constructor-plus-prototype mechanism, with super/static support.

17 What are promises and what states do they have? MEDIUM

A Promise represents a value that will be available later (async). States: pending (initial), fulfilled (resolved with a value), rejected (failed with a reason), and settled = fulfilled or rejected (not pending). Chain with .then(), .catch() and .finally():

fetch(url).then(r => r.json()).catch(e => console.error(e));
18 What is the difference between async/await and promises? MEDIUM

async/await is syntactic sugar over promises that reads like synchronous code. An async function always returns a promise; await pauses it until the promise settles. Errors are handled with try/catch instead of .catch(). It makes complex chains readable but still is promises underneath - you can await any promise.

19 What is an Event Loop and why is JavaScript single-threaded? HARD

JavaScript runs on a single thread but uses an event loop for async work. Long tasks (timers, I/O, promises) are delegated; when the call stack empties, the loop pushes their callbacks in. So: microtasks (Promise callbacks, queueMicrotask) run before the next macrotask (setTimeout, setInterval, I/O). Blocking code stalls the entire loop - that is why heavy loops freeze the page.

20 What is the difference between setTimeout, setInterval and requestAnimationFrame? MEDIUM

setTimeout(fn, ms) runs fn once after a delay; setInterval(fn, ms) runs it repeatedly. Both are macrotasks and their timing is not exact - they run when the loop is free. requestAnimationFrame(fn) schedules fn before the next browser paint - ideal for animations because it syncs with the display refresh rate and pauses in background tabs.

21 What is the difference between microtask and macrotask? HARD

Microtasks (promise .then/.catch callbacks, queueMicrotask) are executed as soon as the current stack finishes, before the next macrotask - higher priority, and a microtask flood can starve rendering. Macrotasks (setTimeout, setInterval, I/O, message events) are queued in the task queue and run one at a time between microtask drains. This ordering is why promises resolve before timers.

22 What are the different ways to copy an object? MEDIUM

Shallow copy: Object.assign({}, obj), the spread operator {...obj}, or Array.from/slice for arrays - nested objects are still shared references. Deep copy: structuredClone(obj) (native), JSON.parse(JSON.stringify(obj)) (loses functions, dates, undefined, symbols), or a library like lodash cloneDeep. Choose shallow for flat data, deep for nested state you must not alias.

23 What is JSON and how do you convert between JSON and JavaScript objects? EASY

JSON is a text format for data interchange based on JavaScript literal syntax but stricter (double quotes, no trailing commas, no functions). JSON.stringify(obj) serializes to a string; JSON.parse(str) parses back to an object. Use them to send data over HTTP or persist it.

24 What is the difference between NaN, Infinity and -Infinity? EASY

NaN (Not-a-Number) results from invalid math like 0/0 and is the only value not equal to itself, so test with Number.isNaN(x). Infinity/-Infinity come from overflow, like 1/0 and -1/0, and are proper numbers. Be careful converting strings: +"abc" is NaN, while Number("10") is 10.

25 What is the difference between Map and WeakMap (and Set/WeakSet)? HARD

Map holds key-value pairs with strong references to keys - keys are never garbage collected, so Maps help when keys must stay alive. WeakMap keys must be objects and are held weakly, so entries disappear when the key object is GC'd - ideal for per-object private metadata/caches. Similarly, Set holds strong references while WeakSet holds objects weakly (no iteration).

26 What is the difference between localStorage, sessionStorage and cookies? MEDIUM

localStorage persists until explicitly removed, ~5-10MB, synchronous, per origin, never sent automatically to the server. sessionStorage is the same but cleared when the tab closes. Cookies are small (~4KB), sent with every matching request (so they handle auth), set with an expiry, and have httpOnly/secure/samesite flags. Choose by need: storage for data, cookies for session/identification.

27 What is event bubbling and event capturing? MEDIUM

When an event fires on an element it travels in two phases: capturing (window/document → down to the target) and then bubbling (target → back up to document). By default listeners run during bubbling. Use addEventListener(evt, fn, {capture: true}) for the capturing phase. Knowing this enables event delegation - one listener on a parent handling many children.

28 What is event delegation and why is it useful? MEDIUM

Event delegation attaches one listener to a common ancestor and uses event.target to react to events on any descendant. It is useful because it needs a single listener (less memory), automatically handles dynamically added elements, and centralizes logic - for example a list where any row click is handled in one place instead of per row.

29 What are the modern ES6+ features you use regularly? EASY

Common modern features: arrow functions, template literals (`hi ${name}`), destructuring and default params, spread/rest, let/const, class syntax, modules (import/export), promises and async/await, Map/Set, Symbol, optional chaining (a?.b), nullish coalescing (a ?? b), Array.of/find/includes/flat, and the nullish assignment. Together they make code shorter and less bug-prone.