JavaScript Interview Questions Comprehensive JavaScript interview questions covering fundamentals, ES6+, async programming, and advanced concepts. These questio…
JavaScript Interview Questions
Comprehensive JavaScript interview questions covering fundamentals, ES6+, async programming, and advanced concepts. These questions are frequently asked in technical interviews.
Fundamentals
1. What is JavaScript?
JavaScript is a high-level, interpreted programming language. It's single-threaded, dynamically typed, and supports multiple programming paradigms (procedural, object-oriented, functional).
2. What are JavaScript data types?
Primitives: string, number, boolean, undefined, null, symbol, bigint. Objects: object, array, function, date, regexp.
3. What is the difference between == and ===?
== performs type coercion before comparison. === checks both value and type without coercion. Always prefer === for predictable behavior.
5 == '5' // true (coercion)
5 === '5' // false (different types)
0 == false // true
0 === false // false
null == undefined // true
null === undefined // false
4. What is the difference between null and undefined?
undefined: variable declared but not assigned. null: intentional absence of value. typeof null is "object" (historical bug), typeof undefined is "undefined".
5. What are falsy values in JavaScript?
false, 0, -0, 0n (BigInt zero), "" (empty string), null, undefined, NaN. Everything else is truthy.
Scope & Closures
6. What is a closure?
A closure is a function that has access to variables in its outer scope, even after the outer function has returned. Closures are created every time a function is created.
function outer() {
const count = 0;
return function inner() {
console.log(count); // Accesses outer scope
};
}
const fn = outer();
fn(); // 0
7. What is the difference between var, let, and const?
var: function-scoped, hoisted, can be redeclared
let: block-scoped, not hoisted to accessible state, cannot be redeclared
const: block-scoped, must be initialized, cannot be reassigned
8. What is hoisting?
Hoisting moves variable and function declarations to the top of their scope. var declarations are hoisted (initialized with undefined). Function declarations are fully hoisted. let/const are hoisted but not initialized (temporal dead zone).
9. What is the temporal dead zone?
The temporal dead zone is the period between entering scope and variable initialization. Accessing let/const variables before declaration causes ReferenceError.
this & Context
10. What is "this" in JavaScript?
"this" refers to the object executing the current function. Its value depends on how the function is called: global (window/global), object method (the object), constructor (new instance), event handler (element), arrow function (lexical this).
11. What is the difference between call(), apply(), and bind()?
call(): invokes function with specified this and arguments individually. apply(): invokes with this and arguments as array. bind(): creates new function with specified this, doesn't invoke immediately.
function greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}
const person = { name: 'John' };
greet.call(person, 'Hello', '!'); // 'Hello, John!'
greet.apply(person, ['Hello', '!']); // 'Hello, John!'
const boundGreet = greet.bind(person, 'Hello');
boundGreet('!'); // 'Hello, John!'
12. How do arrow functions handle "this"?
Arrow functions don't have their own "this". They inherit "this" from the enclosing lexical scope (where they're defined, not where they're called).
Objects & Prototypes
13. What is prototypal inheritance?
Objects can inherit properties and methods from other objects through the prototype chain. Every object has a __proto__ property that points to its prototype.
14. What is the difference between __proto__ and prototype?
__proto__ is the actual object used in the prototype chain lookup. prototype is a property on constructor functions that becomes the __proto__ of instances created with new.
15. How do you create an object without a prototype?
const obj = Object.create(null); // No prototype
console.log(obj.toString); // undefined
Async Programming
16. What is a Promise?
A Promise represents the eventual completion (or failure) of an async operation. States: pending, fulfilled, rejected. Use .then() for success, .catch() for errors, .finally() for cleanup.
17. What is async/await?
async/await is syntactic sugar over Promises. async functions always return a Promise. await pauses execution until Promise resolves, making async code look synchronous.
18. What is the difference between Promise.all() and Promise.race()?
Promise.all(): waits for all promises, fails if any fails. Promise.race(): resolves/rejects with first settled promise. Promise.allSettled(): waits for all, never rejects. Promise.any(): first successful promise.
Event Loop
19. Explain the JavaScript event loop.
The event loop monitors the call stack and callback queue. When the call stack is empty, it moves callbacks from the queue to the stack for execution. Microtasks (Promises) have priority over macrotasks (setTimeout).
20. What is the difference between microtasks and macrotasks?
Microtasks (Promise callbacks, queueMicrotask) execute after current script, before rendering. Macrotasks (setTimeout, setInterval) execute after rendering. Microtasks have higher priority.
Functions
21. What is a higher-order function?
A function that takes another function as argument or returns a function. Examples: map, filter, reduce.
22. What is a pure function?
A function that: 1) Given same inputs, always returns same output. 2) Has no side effects (doesn't modify external state). Makes code predictable and testable.
23. What is function currying?
Currying transforms a function with multiple arguments into a sequence of functions each taking a single argument.
// Normal function
function add(a, b, c) {
return a + b + c;
}
// Curried function
function addCurried(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
const result = addCurried(1)(2)(3); // 6
ES6+ Features
24. What is destructuring?
Destructuring extracts values from arrays or properties from objects into distinct variables. Supports default values, renaming, and nested destructuring.
25. What is the spread operator?
Spread (...) expands iterables into individual elements. Used to copy/merge arrays, clone objects, pass array elements as function arguments.
26. What is the rest operator?
Rest (...) collects multiple elements into an array. Used in function parameters to accept variable number of arguments, or in destructuring to collect remaining elements.
27. What are template literals?
Template literals use backticks for strings. Features: string interpolation ${}, multiline strings, tagged templates.
Arrays & Objects
28. How do you check if a variable is an array?
Array.isArray([1, 2, 3]); // true
Array.isArray('string'); // false
// Don't use:
typeof [] === 'object' // true (not reliable)
[] instanceof Array // true (can fail cross-frame)
29. What is the difference between shallow copy and deep copy?
Shallow copy: copies top-level properties, nested objects/arrays are still referenced. Deep copy: recursively copies all nested structures.
// Shallow copy
const original = { a: 1, b: { c: 2 } };
const shallow = { ...original };
shallow.b.c = 3;
console.log(original.b.c); // 3 (shared reference)
// Deep copy
const deep = JSON.parse(JSON.stringify(original));
// Or use structuredClone()
const deep2 = structuredClone(original);
30. How do you remove duplicates from an array?
const numbers = [1, 2, 2, 3, 3, 4];
const unique = [...new Set(numbers)]; // [1, 2, 3, 4]
// Or
const unique = numbers.filter((val, index, arr) => arr.indexOf(val) === index);
Advanced Concepts
31. What is debouncing?
Debouncing delays function execution until after a specified time has passed since the last invocation. Useful for search inputs, window resize events.
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
}
const search = debounce((query) => {
console.log('Searching for:', query);
}, 300);
// User types 'hello' quickly
search('h'); // Cancelled
search('he'); // Cancelled
search('hel'); // Cancelled
search('hell'); // Cancelled
search('hello'); // Executes after 300ms
32. What is throttling?
Throttling limits function execution to once per specified time period. Useful for scroll events, mouse movements.
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
const handleScroll = throttle(() => {
console.log('Scrolled!');
}, 1000);
window.addEventListener('scroll', handleScroll);
33. What is memoization?
Memoization caches function results for specific inputs to avoid redundant calculations. Optimization technique for expensive operations.
function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
const fibonacci = memoize(function(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
});
fibonacci(40); // Fast with memoization
34. What is the module pattern?
Module pattern uses IIFE and closures to create private variables and expose public API. Provides encapsulation before ES6 modules.
const calculator = (function() {
let result = 0; // Private
return { // Public API
add(n) {
result += n;
return this;
},
getResult() {
return result;
}
};
})();
calculator.add(5).add(3);
console.log(calculator.getResult()); // 8
Practical Questions
35. How do you deep clone an object?
// Method 1: JSON (simple but has limitations)
const clone1 = JSON.parse(JSON.stringify(obj));
// Limitations: loses functions, undefined, symbols, dates become strings
// Method 2: structuredClone (modern, recommended)
const clone2 = structuredClone(obj);
// Method 3: Recursive deep clone
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof Array) return obj.map(item => deepClone(item));
const cloned = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloned[key] = deepClone(obj[key]);
}
}
return cloned;
}
36. What is the difference between map() and forEach()?
map() creates and returns a new array with transformed values. forEach() just iterates, returns undefined. Use map() for transformation, forEach() for side effects.
37. How do you flatten a nested array?
const nested = [1, [2, [3, [4, 5]]]];
// flat() method
nested.flat(); // [1, 2, [3, [4, 5]]]
nested.flat(2); // [1, 2, 3, [4, 5]]
nested.flat(Infinity); // [1, 2, 3, 4, 5]
// Recursive
function flatten(arr) {
return arr.reduce((acc, val) =>
Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val),
[]
);
}
38. How do you reverse a string?
const str = 'hello';
const reversed = str.split('').reverse().join(''); // 'olleh'
// Or with spread
const reversed2 = [...str].reverse().join('');
39. How do you check if a string is a palindrome?
function isPalindrome(str) {
const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, '');
const reversed = cleaned.split('').reverse().join('');
return cleaned === reversed;
}
isPalindrome('A man, a plan, a canal: Panama'); // true
40. How do you find the largest number in an array?
const numbers = [1, 5, 3, 9, 2];
// Method 1: Math.max with spread
const max1 = Math.max(...numbers); // 9
// Method 2: reduce
const max2 = numbers.reduce((max, n) => n > max ? n : max);
// Method 3: sort
const max3 = numbers.sort((a, b) => b - a)[0];
Common Patterns & Best Practices
41. What is event delegation?
Event delegation attaches a single event listener to a parent element instead of multiple listeners to children. Uses event bubbling to handle events from children.
// Instead of this:
const buttons = document.querySelectorAll('button');
buttons.forEach(btn => {
btn.addEventListener('click', handleClick);
});
// Do this:
document.getElementById('container').addEventListener('click', (e) => {
if (e.target.tagName === 'BUTTON') {
handleClick(e);
}
});
42. What is the difference between synchronous and asynchronous code?
Synchronous: executes line by line, blocks until complete. Asynchronous: non-blocking, continues execution, handles result via callbacks/promises when ready.
43. What is event bubbling and capturing?
Event bubbling: events propagate from target up through ancestors. Event capturing: events propagate from root down to target. Use addEventListener(event, handler, true) for capturing phase.
44. What is the difference between stopPropagation() and preventDefault()?
stopPropagation(): stops event from bubbling up. preventDefault(): prevents default browser behavior (e.g., form submission, link navigation).
45. What is strict mode?
"use strict" enables strict mode: prevents use of undeclared variables, makes this undefined in functions, disallows duplicate parameters, and catches silent errors.