Skip to main contentOpteroAIBeta

JavaScript interview questions

JavaScript interview questions covering closures, prototypes, async patterns, the event loop, ES6+ features, and common gotchas.

12 questions
4 easy6 medium2 hard

1.What is a closure, and why is it useful?

easy
How to approach thisA closure is a function that retains access to its outer scope's variables even after the outer function has returned. This enables data privacy (module pattern), partial application, and factory functions. Example: a counter function that returns an increment function which 'remembers' the count variable.

2.Explain the difference between var, let, and const.

easy
How to approach thisvar is function-scoped and hoisted (initialized as undefined). let and const are block-scoped and hoisted but not initialized (temporal dead zone). const prevents reassignment but does not make objects immutable (you can still mutate properties). Use const by default, let when you need reassignment, and never use var.

3.What is the difference between == and ===?

easy
How to approach this== performs type coercion before comparing (1 == '1' is true). === checks both value and type without coercion (1 === '1' is false). Type coercion rules are complex and unintuitive ([] == false is true). Always use === to avoid subtle bugs. The only reasonable use of == is checking for null/undefined with x == null.

4.Explain how prototypal inheritance works in JavaScript.

medium
How to approach thisEvery object has an internal [[Prototype]] link to another object. When accessing a property, JS walks up the prototype chain until it finds it or reaches null. Object.create(proto) creates an object with the given prototype. ES6 classes are syntactic sugar over this mechanism. Understanding the chain explains how methods like toString() are available on all objects.

5.What are Promises, and how do they improve over callbacks?

medium
How to approach thisA Promise represents a future value (pending, fulfilled, or rejected). They improve over callbacks by: chaining (.then returns a new Promise), centralized error handling (.catch), composition (Promise.all, Promise.race), and avoiding callback hell (nested callbacks). async/await is syntactic sugar over Promises that makes async code look synchronous.

6.Explain the difference between function declarations and arrow functions.

medium
How to approach thisArrow functions do not have their own 'this' (they inherit from the enclosing scope), cannot be used as constructors (no new), and do not have an 'arguments' object. Function declarations are hoisted and have their own 'this' (determined by how they are called). Use arrow functions for callbacks and methods that need lexical 'this'; use function declarations for standalone functions.

7.What is event delegation, and why is it useful?

medium
How to approach thisEvent delegation attaches a single event listener to a parent element instead of individual listeners on each child. It works because events bubble up the DOM. Check event.target to identify which child was clicked. Benefits: works for dynamically added elements, uses less memory, and requires less setup code. Essential for large lists.

8.How does the 'this' keyword work in JavaScript?

hard
How to approach thisthis depends on how a function is called: method call (obj.method() -> obj), plain call (func() -> undefined in strict mode, window in sloppy), constructor (new Func() -> new object), explicit binding (call/apply/bind -> specified value). Arrow functions inherit this from their enclosing scope. This is one of the most confusing parts of JS.

9.What are WeakMap and WeakSet, and when would you use them?

hard
How to approach thisWeakMap holds key-value pairs where keys are objects and are held weakly (garbage collected if no other references). WeakSet holds objects weakly. Use WeakMap for: private data associated with objects, caching without memory leaks, tracking DOM nodes without preventing garbage collection. They are not iterable and have no size property.

10.Explain the Module pattern in JavaScript and how ES Modules differ from CommonJS.

medium
How to approach thisES Modules use import/export (static, tree-shakeable, async loading). CommonJS uses require/module.exports (dynamic, synchronous, used in Node.js). ES Modules are the standard going forward. CommonJS modules are evaluated once and cached. ES Modules have live bindings (importing a reference, not a copy). Node.js supports both via .mjs extension or package.json type field.

11.What is the difference between shallow copy and deep copy in JavaScript?

easy
How to approach thisShallow copy (spread operator, Object.assign) copies top-level properties but nested objects are still references. Deep copy (structuredClone(), JSON.parse(JSON.stringify())) recursively copies all levels. JSON method fails on functions, Dates, undefined, and circular references. structuredClone (available in modern runtimes) handles most cases correctly.

12.How would you debounce and throttle a function? What is the difference?

medium
How to approach thisDebounce delays execution until after a pause in calls (good for search input: wait until user stops typing). Throttle limits execution to at most once per interval (good for scroll handlers: fire at most every 100ms). Implement debounce with clearTimeout/setTimeout. Implement throttle with a timestamp check or a flag. Lodash provides battle-tested versions of both.

Prepare further

More interview topics