Interview Prep

JavaScript Interview Questions and Answer

JavaScript interviews test your understanding of core language features, asynchronous programming, scope, closures, and problem-solving skills. This comprehensive guide covers 50+ frequently asked interview questions — from beginner fundamentals to advanced concepts — with clear explanations and practical code examples.

1–10: Basics & Variables

Q1 What is the difference between var, let, and const?
  • var — function-scoped, can be re-declared, hoisted with undefined.
  • let — block-scoped, cannot be re-declared in the same scope, hoisted but not initialized (Temporal Dead Zone).
  • const — block-scoped, cannot be re-declared or reassigned (but object properties can be mutated).
var a = 1;
        let b = 2;
        const c = 3;
        // c = 4; // TypeError
Q2 What is the difference between == and ===?
  • == — abstract equality, performs type coercion before comparison.
  • === — strict equality, compares both value and type without coercion.
console.log(2 == '2');   // true (coercion)
        console.log(2 === '2');  // false (type mismatch)
Always prefer === for predictable behavior.
Q3 What is hoisting in JavaScript?
Hoisting is the behavior where variable and function declarations are moved to the top of their scope during compilation. var declarations are hoisted with undefined, while let and const are hoisted but not initialized.
console.log(x); // undefined (hoisted)
        var x = 5;
        // console.log(y); // ReferenceError (TDZ)
        let y = 10;
Function declarations are hoisted entirely.
Q4 What is the difference between null and undefined?
  • undefined — a variable has been declared but not assigned a value.
  • null — an intentionally assigned empty value, representing "no value".
let a;
        console.log(a); // undefined
        let b = null;
        console.log(b); // null
        console.log(typeof null); // 'object' (historical quirk)
Q5 What are JavaScript data types?
Primitive (7): string, number, bigint, boolean, undefined, symbol, null.
Non-primitive: object (includes arrays, functions, dates, etc.).
console.log(typeof 'hello'); // string
        console.log(typeof 42);     // number
        console.log(typeof {});     // object
        console.log(typeof []);     // object (array is an object)
Q6 What is the Temporal Dead Zone (TDZ)?
The TDZ is the period between entering a scope and the actual declaration of a let or const variable. Accessing the variable during this period throws a ReferenceError.
// TDZ starts here
        console.log(x); // ReferenceError
        let x = 5;      // TDZ ends here
Q7 What is the difference between NaN and undefined?
NaN (Not-a-Number) is a numeric value that represents an invalid number. undefined means a variable has no value assigned. typeof NaN returns 'number'.
console.log(typeof NaN); // 'number'
        console.log(NaN === NaN); // false (NaN is not equal to itself)
Q8 What is the typeof operator used for?
typeof returns a string indicating the type of the operand. It's useful for type checking, but has quirks (e.g., typeof null === 'object').
console.log(typeof 42);          // 'number'
        console.log(typeof 'hello');    // 'string'
        console.log(typeof undefined);  // 'undefined'
        console.log(typeof null);       // 'object' (bug in JS)
        console.log(typeof function(){}); // 'function'
Q9 What is the difference between ++i and i++?
  • ++i (pre-increment) — increments the value and returns the new value.
  • i++ (post-increment) — returns the current value, then increments.
let i = 5;
        console.log(++i); // 6 (i becomes 6, then logged)
        let j = 5;
        console.log(j++); // 5 (logged, then j becomes 6)
Q10 How do you check if a variable is an array?
Use Array.isArray() — it's the safest method.
let arr = [1, 2, 3];
        console.log(Array.isArray(arr)); // true
        console.log(Array.isArray({}));   // false
instanceof Array can fail across frames.

11–20: Functions & Scope

Q11 What is a closure?
A closure is a function that remembers its lexical scope even when the function is executed outside that scope. It allows inner functions to access variables from an outer function after the outer function has returned.
function outer() {
          let count = 0;
          return function inner() {
            count++;
            return count;
          };
        }
        const counter = outer();
        console.log(counter()); // 1
        console.log(counter()); // 2
Closures are used for data privacy, currying, and event handlers.
Q12 What is the difference between function declarations and function expressions?
  • Function declaration: hoisted entirely, can be called before definition.
  • Function expression: not hoisted, only defined when the interpreter reaches that line.
// Function declaration
        console.log(add(2, 3)); // 5
        function add(a, b) { return a + b; }
        
        // Function expression
        // console.log(sub(5, 2)); // TypeError
        const sub = function(a, b) { return a - b; };
Q13 What are arrow functions? How do they differ from regular functions?
Arrow functions are a shorter syntax introduced in ES6. Key differences:
  • No this binding — they inherit this from the enclosing scope.
  • Cannot be used as constructors (no new).
  • No arguments object (use rest parameters instead).
  • Implicit return for single-expression bodies.
const add = (a, b) => a + b;
        const square = n => n * n;
        // this binding example
        const obj = {
          name: 'John',
          greet: () => console.log(this.name) // this refers to outer scope
        };
Q14 What is the this keyword in JavaScript?
this refers to the context in which a function is called. Its value depends on how the function is invoked:
  • Global: this === window (browser) or global (Node).
  • Object method: this refers to the object.
  • Constructor: this refers to the new instance.
  • Arrow function: this is lexically bound.
  • Explicit binding: call(), apply(), bind().
const obj = {
          name: 'Alice',
          greet() { console.log(this.name); }
        };
        obj.greet(); // 'Alice'
Q15 What is the difference between call(), apply(), and bind()?
All three are used to set the this value explicitly.
  • call() — invokes the function with a given this and arguments (comma-separated).
  • apply() — same as call(), but arguments are passed as an array.
  • bind() — returns a new function with a bound this (does not invoke immediately).
function greet(greeting) {
          console.log(greeting + ', ' + this.name);
        }
        const user = { name: 'Bob' };
        greet.call(user, 'Hello');   // 'Hello, Bob'
        greet.apply(user, ['Hi']);    // 'Hi, Bob'
        const bound = greet.bind(user, 'Hey');
        bound();                      // 'Hey, Bob'
Q16 What is the difference between arguments and rest parameters?
  • arguments — an array-like object available inside regular functions (not arrow functions). Has length but lacks array methods.
  • Rest parameters...args syntax, returns a real array, works in arrow functions.
function regular() {
          console.log(arguments.length);
        }
        const arrow = (...args) => console.log(args.length);
        regular(1, 2, 3); // 3
        arrow(1, 2, 3);   // 3
Q17 What is a higher-order function?
A higher-order function is a function that takes another function as an argument, returns a function, or both. Examples: map(), filter(), reduce().
function applyTwice(fn, value) {
          return fn(fn(value));
        }
        const result = applyTwice(x => x * 2, 3);
        console.log(result); // 12
Q18 What is a pure function?
A pure function has two key properties:
  • Always returns the same output for the same input (deterministic).
  • No side effects (does not modify external state).
// Pure
        function add(a, b) { return a + b; }
        // Impure (modifies external state)
        let count = 0;
        function increment() { count++; }
Q19 What is the difference between function and => for methods in objects?
Regular functions in objects have their own this binding to the object. Arrow functions inherit this from the outer scope (which may be the global scope), so they are not suitable for object methods if you need to access the object.
const obj = {
          name: 'Test',
          regular: function() { console.log(this.name); }, // 'Test'
          arrow: () => console.log(this.name) // undefined (global this)
        };
        obj.regular();
        obj.arrow();
Q20 What is a callback function?
A callback is a function passed as an argument to another function, to be executed later (often after an asynchronous operation completes).
function fetchData(callback) {
          setTimeout(() => {
            callback('Data received');
          }, 1000);
        }
        fetchData((data) => console.log(data));
Callbacks are the foundation of asynchronous programming in JavaScript.

21–30: Objects & Prototypes

Q21 What is prototype inheritance in JavaScript?
JavaScript uses prototypal inheritance — objects can inherit properties and methods from other objects via the prototype chain. Every object has an internal [[Prototype]] link (accessed via __proto__ or Object.getPrototypeOf()).
const parent = { greet: 'Hello' };
        const child = Object.create(parent);
        console.log(child.greet); // 'Hello' (inherited)
Q22 What is the difference between Object.create() and new?
  • Object.create(proto) — creates a new object with the specified prototype.
  • new Constructor() — creates a new object using a constructor function and sets the prototype to Constructor.prototype.
const proto = { shared: 'value' };
        const obj1 = Object.create(proto);
        function Person(name) { this.name = name; }
        const obj2 = new Person('John');
Q23 What is the class syntax in JavaScript?
ES6 introduced class syntax — syntactic sugar over prototype-based inheritance. It provides a cleaner way to define constructor functions and methods.
class Animal {
          constructor(name) { this.name = name; }
          speak() { console.log(this.name + ' makes a noise.'); }
        }
        class Dog extends Animal {
          speak() { console.log(this.name + ' barks.'); }
        }
        const d = new Dog('Rex');
        d.speak(); // 'Rex barks.'
Q24 What is the difference between Object.freeze() and Object.seal()?
  • Object.freeze() — prevents adding, deleting, or modifying properties (makes the object immutable).
  • Object.seal() — prevents adding or deleting properties, but existing properties can still be modified.
const obj = { a: 1 };
        Object.freeze(obj);
        obj.a = 2; // silently fails (or TypeError in strict mode)
        console.log(obj.a); // 1
Q25 How do you clone an object?
  • Shallow copy: spread ({...obj}) or Object.assign({}, obj).
  • Deep copy: structuredClone(obj) (modern) or JSON.parse(JSON.stringify(obj)) (with limitations).
const original = { a: 1, b: { c: 2 } };
        const shallow = { ...original };
        shallow.b.c = 42; // modifies original.b.c too
        const deep = structuredClone(original);
        deep.b.c = 99;    // original.b.c remains 42
Q26 What is the difference between for...in and for...of?
  • for...in — iterates over enumerable property keys (including inherited) of an object.
  • for...of — iterates over iterable values (arrays, strings, maps, sets, etc.).
const arr = ['a', 'b', 'c'];
        for (let key in arr) console.log(key); // '0', '1', '2'
        for (let value of arr) console.log(value); // 'a', 'b', 'c'
Q27 What is the difference between Map and Object?
  • Map — keys can be any type (including objects), preserves insertion order, has size property, and is iterable.
  • Object — keys are strings or symbols, has prototype inheritance, and is not directly iterable.
const map = new Map();
        map.set('key', 'value');
        map.set(42, 'number');
        console.log(map.get(42)); // 'number'
Q28 What is a Set in JavaScript?
A Set is a collection of unique values (no duplicates). It maintains insertion order and works with any value type.
const set = new Set([1, 2, 2, 3]);
        console.log(set); // Set { 1, 2, 3 }
        set.add(4);
        console.log(set.has(3)); // true
        set.delete(2);
Q29 How do you check if an object has a property?
Use hasOwnProperty() (own property) or the in operator (includes inherited properties).
const obj = { a: 1 };
        console.log(obj.hasOwnProperty('a')); // true
        console.log(obj.hasOwnProperty('toString')); // false
        console.log('toString' in obj); // true (inherited)
Q30 What is the difference between Object.keys(), Object.values(), and Object.entries()?
  • Object.keys(obj) — returns an array of enumerable property keys.
  • Object.values(obj) — returns an array of enumerable property values.
  • Object.entries(obj) — returns an array of [key, value] pairs.
const obj = { a: 1, b: 2, c: 3 };
        console.log(Object.keys(obj));   // ['a', 'b', 'c']
        console.log(Object.values(obj)); // [1, 2, 3]
        console.log(Object.entries(obj)); // [['a',1], ['b',2], ['c',3]]

31–40: Async & Event Loop

Q31 What is the event loop in JavaScript?
The event loop is the mechanism that allows JavaScript (which is single-threaded) to handle asynchronous operations. It continuously checks the call stack and the task queue, pushing tasks from the queue to the stack when the stack is empty.
console.log('Start');
        setTimeout(() => console.log('Timeout'), 0);
        Promise.resolve().then(() => console.log('Promise'));
        console.log('End');
        // Output: Start, End, Promise, Timeout
Microtasks (promises) have higher priority than macrotasks (setTimeout).
Q32 What is the difference between synchronous and asynchronous code?
  • Synchronous: code runs sequentially, blocking further execution until the current operation completes.
  • Asynchronous: code runs non-blocking; operations like network requests, timers, or file I/O are delegated to the browser/Node, and callbacks are executed later.
// Synchronous
        console.log('A');
        console.log('B'); // B runs after A
        // Asynchronous
        console.log('A');
        setTimeout(() => console.log('B'), 0);
        console.log('C'); // C runs before B
Q33 What is a Promise?
A Promise is an object representing the eventual completion (or failure) of an asynchronous operation. It has three states: pending, fulfilled, or rejected.
const promise = new Promise((resolve, reject) => {
          setTimeout(() => resolve('Success!'), 1000);
        });
        promise.then(value => console.log(value)) // 'Success!'
               .catch(err => console.error(err));
Q34 What is the difference between Promise.all() and Promise.allSettled()?
  • Promise.all() — rejects immediately if any promise rejects; resolves with an array of values if all resolve.
  • Promise.allSettled() — waits for all promises to settle (fulfill or reject) and returns an array of status objects.
Promise.all([p1, p2]).then(v => console.log(v));
        Promise.allSettled([p1, p2]).then(results => {
          results.forEach(r => console.log(r.status));
        });
Q35 What is async/await?
async/await is syntactic sugar built on promises, making asynchronous code look and behave more like synchronous code. An async function returns a promise, and await pauses execution until the promise resolves.
async function fetchData() {
          try {
            const response = await fetch('https://api.example.com');
            const data = await response.json();
            console.log(data);
          } catch (error) {
            console.error(error);
          }
        }
Q36 What is callback hell and how do you avoid it?
Callback hell (or "Pyramid of Doom") occurs when multiple nested callbacks make code difficult to read and maintain. It can be avoided using:
  • Promises with chaining (.then())
  • async/await (most readable)
  • Breaking functions into smaller, named functions
// Callback hell
        doA(() => {
          doB(() => {
            doC(() => console.log('Done'));
          });
        });
        // With async/await
        async function run() {
          await doA();
          await doB();
          await doC();
          console.log('Done');
        }
Q37 What is the difference between setTimeout and setInterval?
  • setTimeout(fn, delay) — executes the function once after the specified delay.
  • setInterval(fn, interval) — repeatedly executes the function every interval milliseconds.
setTimeout(() => console.log('Once'), 1000);
        const id = setInterval(() => console.log('Repeating'), 2000);
        clearInterval(id); // stop after some time
Q38 What is a microtask vs macrotask?
  • Microtasks: Promise.then(), queueMicrotask(), MutationObserver. They run immediately after the current stack, before any macrotasks.
  • Macrotasks: setTimeout(), setInterval(), I/O, UI rendering. They run in the next iteration of the event loop.
console.log('1');
        setTimeout(() => console.log('2'), 0);
        Promise.resolve().then(() => console.log('3'));
        console.log('4');
        // Output: 1, 4, 3, 2
Q39 What is fetch() and how does it work?
fetch() is a modern API for making network requests. It returns a Promise that resolves to a Response object.
fetch('https://api.example.com/data')
          .then(response => response.json())
          .then(data => console.log(data))
          .catch(err => console.error(err));
        
        // With async/await
        async function getData() {
          const res = await fetch('https://api.example.com/data');
          const data = await res.json();
          return data;
        }
Q40 What is the difference between try/catch with async/await and .catch() with promises?
They are equivalent in functionality. try/catch with await provides a more synchronous-looking syntax for error handling.
// Promise style
        fetch(url)
          .then(res => res.json())
          .catch(err => console.error(err));
        
        // async/await style
        try {
          const res = await fetch(url);
          const data = await res.json();
        } catch (err) {
          console.error(err);
        }
The try/catch approach is often more readable, especially with multiple awaits.

41–50: ES6+ & Advanced

Q41 What is destructuring in JavaScript?
Destructuring allows unpacking values from arrays or properties from objects into distinct variables.
// Array destructuring
        const [a, b] = [1, 2];
        console.log(a, b); // 1, 2
        // Object destructuring
        const { name, age } = { name: 'John', age: 30 };
        console.log(name, age); // 'John', 30
It can be used with default values, rest patterns, and nested structures.
Q42 What are template literals?
Template literals are string literals using backticks (`) that support embedded expressions via ${} and multi-line strings.
const name = 'Alice';
        const greeting = `Hello, ${name}!
        Welcome to the course.`;
        console.log(greeting);
Q43 What is the spread operator (...) and what is it used for?
The spread operator expands an iterable (array, string, object) into individual elements. Common uses:
  • Copying arrays/objects: [...arr], {...obj}
  • Merging arrays/objects: [...a, ...b]
  • Function arguments: Math.max(...nums)
const arr1 = [1, 2];
        const arr2 = [3, 4];
        const merged = [...arr1, ...arr2]; // [1, 2, 3, 4]
Q44 What is the rest parameter?
The rest parameter (...args) collects remaining arguments into a real array. It is used in function definitions to handle variable numbers of arguments.
function sum(...numbers) {
          return numbers.reduce((acc, n) => acc + n, 0);
        }
        console.log(sum(1, 2, 3, 4)); // 10
Q45 What is the difference between import and require()?
  • require() — CommonJS, synchronous, used in Node.js (and older bundlers).
  • import — ES6 module syntax, asynchronous, used in modern JavaScript (both browser and Node with type:module).
// CommonJS
        const module = require('./module');
        // ES6
        import module from './module.js';
Q46 What is the Symbol data type?
Symbol is a primitive data type introduced in ES6. Each symbol is unique and immutable, often used as object property keys to avoid name collisions.
const sym1 = Symbol('id');
        const sym2 = Symbol('id');
        console.log(sym1 === sym2); // false
        const obj = { [sym1]: 'value' };
        console.log(obj[sym1]); // 'value'
Q47 What are getters and setters in JavaScript?
Getters and setters are special methods that allow you to define how a property is accessed and modified. They are defined using get and set keywords.
const obj = {
          _name: '',
          get name() { return this._name; },
          set name(value) { this._name = value.trim(); }
        };
        obj.name = '  John  ';
        console.log(obj.name); // 'John'
Q48 What is the difference between forEach() and map()?
  • forEach() — iterates over each element, executes a callback, but does not return a new array (returns undefined).
  • map() — creates a new array by applying a function to each element.
const arr = [1, 2, 3];
        arr.forEach(n => console.log(n)); // logs 1,2,3
        const doubled = arr.map(n => n * 2); // [2, 4, 6]
Q49 What is a generator function?
A generator function (function*) returns a generator object that can be used to control the execution of the function. It uses yield to pause and resume execution.
function* countUp() {
          let i = 0;
          while (true) {
            yield i++;
          }
        }
        const gen = countUp();
        console.log(gen.next().value); // 0
        console.log(gen.next().value); // 1
        console.log(gen.next().value); // 2
Q50 What is the new operator doing under the hood?
When you use new Constructor():
  1. A new empty object is created.
  2. The object's prototype is set to Constructor.prototype.
  3. The constructor is called with this bound to the new object.
  4. If the constructor returns an object, that object is returned; otherwise, the new object is returned.
function Person(name) { this.name = name; }
        const p = new Person('Alice');
        console.log(p.name); // 'Alice'

51–55: DOM & Miscellaneous

Q51 What is the DOM?
The DOM (Document Object Model) is a programming interface for HTML documents. It represents the page as a tree of nodes, allowing JavaScript to manipulate the structure, style, and content of a web page.
// Selecting and modifying an element
        const el = document.getElementById('myId');
        el.textContent = 'New text';
        el.style.color = 'red';
Q52 What is event delegation?
Event delegation is a technique where you attach a single event listener to a parent element, and use event bubbling to handle events on child elements. This improves performance and handles dynamically added elements.
document.querySelector('#parent').addEventListener('click', (e) => {
          if (e.target.matches('.child')) {
            console.log('Child clicked:', e.target.textContent);
          }
        });
Q53 What is the difference between stopPropagation() and preventDefault()?
  • stopPropagation() — prevents the event from bubbling up the DOM tree.
  • preventDefault() — prevents the default action of the event (e.g., form submission, link navigation).
anchor.addEventListener('click', (e) => {
          e.preventDefault(); // prevents navigation
          e.stopPropagation(); // prevents parent handlers
        });
Q54 What is localStorage and sessionStorage?
Both are web storage APIs for storing key-value pairs in the browser.
  • localStorage — persists data even after the browser is closed (no expiration).
  • sessionStorage — persists data only for the duration of the page session (cleared when the tab is closed).
localStorage.setItem('key', 'value');
        const val = localStorage.getItem('key');
        localStorage.removeItem('key');
Q55 What is a Cookie and how does it differ from localStorage?
Cookies are small pieces of data stored by the browser, sent with every HTTP request to the server. They have expiration dates and size limits (~4KB). localStorage is client-side only, persists longer, and has a larger limit (~5–10MB).
// Setting a cookie
        document.cookie = 'username=John; expires=...; path=/';
        // localStorage is simpler
        localStorage.setItem('username', 'John');

  Pro Tip: Practice writing code for each concept. Understanding the theory is important, but being able to implement solutions quickly is what sets you apart in interviews.

Ready to master real-world JavaScript development?

Learn JavaScript hands-on with mentor-led, live sessions.

Explore Course