JavaScript Interview Questions - Core Concepts
40 interview questions on closures, the event loop, call stack, this keyword, execution context, prototypes, and scope.
40 interview questions on closures, the event loop, call stack, this keyword, execution context, prototypes, and scope. This interview-focused guide covers essential javascript interview questions - core concepts concepts for technical interviews.
JavaScript Interview Questions – Core Concepts
These 40 questions cover the intermediate concepts that separate junior from senior JavaScript developers: closures, the event loop, this binding, execution context, prototype-based inheritance, and scope mechanics.
1. What is a closure?
A closure is a function that retains access to its lexical scope even when executed outside that scope. It "remembers" the variables from where it was created.
function createCounter() {
let count = 0;
return function() { count++; return count; };
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
[!TIP] Common use cases: Data privacy, function factories, memoization, module pattern, currying.
2. How does the event loop work?
The event loop is JavaScript's mechanism for handling asynchronous operations. It continuously checks the call stack and moves callbacks from queues to the stack when the stack is empty.
Call Stack → Web APIs → Callback/Task Queue → Event Loop → Call Stack
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
// Output: 1, 4, 3, 2
3. What is the difference between microtasks and macrotasks?
| Type | Examples | Priority |
|---|---|---|
| Microtasks | Promise.then/catch/finally, queueMicrotask, MutationObserver | Higher |
| Macrotasks | setTimeout, setInterval, I/O, UI rendering | Lower |
[!IMPORTANT] The event loop drains ALL microtasks before moving to the next macrotask. This is why
3prints before2in the example above.
4. Explain this keyword behavior
The value of this depends on how a function is called, not where it's defined:
| Context | this refers to |
|---|---|
| Global (non-strict) | window / globalThis |
| Global (strict mode) | undefined |
| Object method | The object calling the method |
Constructor (new) | The new instance being created |
| Arrow function | Lexical this (from enclosing scope) |
call() / apply() / bind() | Explicitly set value |
const obj = {
name: "Alice",
regular() { console.log(this.name); }, // "Alice"
arrow: () => console.log(this.name) // undefined
};
5. What is the call stack?
The call stack is a LIFO (Last In, First Out) data structure that tracks function execution. Each function call creates a stack frame; each return removes one. A stack overflow happens when too many frames accumulate (e.g., infinite recursion).
6. What is the execution context?
An execution context is the environment in which JavaScript code is evaluated and executed. It has two phases:
- Creation Phase: Scope chain,
thisbinding, hoisted declarations - Execution Phase: Assigns values, executes code line by line
Three types: Global, Function, and Eval execution contexts.
7. What is the prototype chain?
Every JavaScript object has an internal [[Prototype]] link (__proto__). When accessing a property, JS walks up this chain until it finds the property or reaches null.
const arr = [1, 2, 3];
// arr -> Array.prototype -> Object.prototype -> null
8. What's the difference between prototypal and classical inheritance?
- Classical (Java, C++): Classes are blueprints; objects are instances. Inheritance copies behavior.
- Prototypal (JavaScript): Objects inherit directly from objects via the prototype chain. No copying — delegation.
[!TIP] ES6
classsyntax is syntactic sugar over JavaScript's prototypal inheritance.
9. What is the difference between call, apply, and bind?
call(thisArg, arg1, arg2, ...)— invokes immediatelyapply(thisArg, [args])— invokes immediately with array argbind(thisArg, arg1, ...)— returns a new bound function, does NOT invoke
10. What is the module pattern?
Uses closures to create private variables and expose a public API. The classic pattern before ES6 modules.
const counter = (function() {
let count = 0;
return {
increment: () => ++count,
getCount: () => count
};
})();
11. What is currying?
Transforms a function with multiple arguments into a sequence of functions each taking a single argument.
const add = a => b => c => a + b + c;
console.log(add(1)(2)(3)); // 6
12. What is memoization?
Caches function results to avoid redundant computations.
function memoize(fn) {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (!cache.has(key)) cache.set(key, fn(...args));
return cache.get(key);
};
}
13. What is debouncing?
Ensures a function is only called after a specified delay since the last invocation. Used for search inputs, resize handlers.
function debounce(fn, delay) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => fn(...args), delay);
};
}
14. What is throttling?
Ensures a function is called at most once in a specified time period. Used for scroll events, button clicks.
15. What is an IIFE?
An Immediately Invoked Function Expression executes as soon as it's defined. Creates a private scope.
(function() { console.log("Runs immediately!"); })();
16. What is the difference between Function Declaration and Function Expression?
- Declaration:
function foo() {}— hoisted, can be called before definition - Expression:
const foo = function() {}— not hoisted, TDZ applies withlet/const
17. What are first-class functions?
In JavaScript, functions are first-class citizens — they can be assigned to variables, passed as arguments, returned from other functions, and stored in data structures.
18. What is a higher-order function?
A function that takes another function as an argument or returns a function.
[1, 2, 3].map(x => x * 2); // Takes a function
function multiplyBy(n) { return x => x * n; } // Returns a function
19. What is a pure function?
A function that: (1) returns the same output for the same input, (2) has no side effects. Pure functions are predictable, testable, and cacheable.
20. What is a side effect?
Any operation that modifies state outside the function scope — modifying global variables, DOM manipulation, API calls, console.log, writing to files.
21. What is function composition?
Combines multiple functions where the output of one becomes the input of the next.
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
22. What is a generator function?
A function that can pause and resume execution using yield.
function* gen() { yield 1; yield 2; yield 3; }
const g = gen();
console.log(g.next().value); // 1
23. What is new keyword doing?
- Creates an empty object
- Sets
thisto the new object - Links the object's
[[Prototype]]to the constructor'sprototype - Executes the constructor function
- Returns the new object (unless constructor returns a non-primitive)
24. What is the difference between Object.create() and new?
new Constructor()— calls the constructor function, sets up prototype chainObject.create(proto)— creates an object with specified prototype, no constructor call
25. What is the arguments object?
An array-like object accessible inside functions that contains all passed arguments. NOT available in arrow functions.
[!NOTE] In modern JS, rest parameters (
...args) are preferred overarguments.
26. What are default parameters?
ES6 feature that sets default values for function parameters when undefined is passed.
function greet(name = "Guest") { return `Hello, ${name}`; }
27. What is a callback function?
A function passed as an argument to another function, to be executed later (synchronously or asynchronously).
28. What is "callback hell"?
Deeply nested callbacks that become unreadable. Solved by Promises and async/await.
29. What is recursion?
A function that calls itself. Must have a base case to prevent infinite recursion.
function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); }
30. What is tail call optimization (TCO)?
An optimization where the compiler can reuse the current stack frame for tail-recursive calls. Supported in strict mode ES6+ but limited browser support.
31. What is an arrow function's this binding?
Arrow functions do NOT have their own this. They inherit this from the enclosing lexical scope. This binding cannot be changed with call, apply, or bind.
32. What does Function.prototype.bind() return?
A new function with this permanently bound and optional pre-filled arguments. The bound function cannot be re-bound.
33. What is the difference between slice() and splice()?
slice(start, end)— returns a shallow copy (does NOT mutate)splice(start, deleteCount, ...items)— modifies the array in place
34. What is array destructuring?
Extracts values from arrays into variables.
const [a, b, ...rest] = [1, 2, 3, 4, 5];
35. What is object destructuring?
Extracts properties from objects into variables.
const { name, age = 25 } = { name: "Alice" };
36. What is the spread operator in objects?
Creates a shallow copy of an object's enumerable own properties.
const copy = { ...original };
const merged = { ...defaults, ...overrides };
37. What is optional chaining (?.)?
Safely accesses nested properties without checking each level.
const city = user?.address?.city; // undefined instead of error
38. What is nullish coalescing (??)?
Returns right operand only when left is null or undefined (not 0 or "").
const count = 0 ?? 10; // 0
const name = null ?? "Guest"; // "Guest"
39. What is the typeof operator limitation for arrays?
typeof [] returns "object". Use Array.isArray([]) to check for arrays.
40. What is instanceof used for?
Tests if an object's prototype chain contains a constructor's prototype.
console.log([] instanceof Array); // true
console.log({} instanceof Object); // true