Menu

HTML & JS Topic

Top 30 JavaScript Interview Questions & Answers

Core JavaScript Concepts

1. What is the difference between let, const, and var?

Answer:

  • var: Function-scoped, hoisted, can be redeclared, initialized with undefined

  • let: Block-scoped, hoisted but not initialized (TDZ), cannot be redeclared in same scope

  • const: Block-scoped, must be initialized, cannot be reassigned (but object properties can be modified)

javascript

// Temporal Dead Zone example
console.log(x); // ReferenceError (TDZ)
let x = 5;

2. Explain closures with an example

Answer: A closure is a function that retains access to variables from its outer (enclosing) scope even after the outer function has returned.

javascript

function outer() {
    let count = 0;
    return function inner() {
        count++;
        return count;
    };
}
const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2
// 'count' persists due to closure

3. What is hoisting in JavaScript?

Answer: JavaScript's behavior of moving declarations to the top of their scope during compilation.

  • Function declarations: Fully hoisted (can be called before declaration)

  • var variables: Hoisted but initialized as undefined

  • let/const: Hoisted but not initialized (Temporal Dead Zone)

  • Function expressions: Follow variable hoisting rules

4. Explain the this keyword in different contexts

Answer: this refers to the execution context:

javascript

// 1. Global context: `this` refers to window/global object
// 2. Object method: `this` refers to the object
const obj = { 
    name: 'John', 
    greet() { return `Hello, ${this.name}`; }
};

// 3. Constructor function: `this` refers to new instance
function Person(name) { this.name = name; }

// 4. Arrow function: `this` is lexically bound (inherits from parent scope)
// 5. Event handler: `this` refers to the element that received the event
// 6. Explicit binding: call(), apply(), bind()

5. What are promises and how do they work?

Answer: Promises represent the eventual completion or failure of an asynchronous operation.

javascript

const promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve('Success!'), 1000);
});

promise
    .then(result => console.log(result))
    .catch(error => console.error(error))
    .finally(() => console.log('Done'));

// Promise states: pending, fulfilled, rejected

Intermediate JavaScript Questions

6. Explain the event loop and how async code works

Answer: JavaScript has a single-threaded event loop with:

  • Call Stack: Executes synchronous code

  • Web APIs: Browser-provided APIs (setTimeout, DOM events, HTTP requests)

  • Callback Queue: Holds callbacks from Web APIs

  • Microtask Queue: For promises and MutationObserver (higher priority)

Execution order: Call Stack → Microtasks → Callback Queue

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

Answer:

  • == (loose equality): Performs type coercion before comparison

  • === (strict equality): No type coercion, compares type and value

javascript

0 == false     // true (coercion)
0 === false    // false (different types)
null == undefined  // true
null === undefined // false

8. Explain call, apply, and bind methods

Answer: Methods to explicitly set this value:

javascript

const person = { name: 'Alice' };

function greet(greeting, punctuation) {
    return `${greeting}, ${this.name}${punctuation}`;
}

// call(): Invokes immediately with arguments passed individually
greet.call(person, 'Hello', '!');  // "Hello, Alice!"

// apply(): Invokes immediately with arguments as array
greet.apply(person, ['Hi', '.']);  // "Hi, Alice."

// bind(): Returns new function with bound context
const boundGreet = greet.bind(person, 'Hey');
boundGreet('?');  // "Hey, Alice?"

9. What are arrow functions and their limitations?

Answer:
Features:

  • Shorter syntax

  • Lexical this (inherits from parent scope)

  • No arguments object

  • Cannot be used as constructors

Limitations:

  • No own this, super, arguments

  • Cannot use new keyword

  • Not suitable for object methods when dynamic this is needed

  • No function hoisting (assigned to variables)

10. Explain prototypal inheritance

Answer: JavaScript uses prototype-based inheritance where objects inherit from other objects.

javascript

function Animal(name) {
    this.name = name;
}

Animal.prototype.speak = function() {
    return `${this.name} makes a sound`;
};

function Dog(name) {
    Animal.call(this, name); // Call parent constructor
}

// Set up prototype chain
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.speak = function() {
    return `${this.name} barks`;
};

const dog = new Dog('Rex');
console.log(dog.speak()); // "Rex barks"

Advanced JavaScript Questions

11. What is the event delegation pattern?

Answer: Attaching a single event listener to a parent element to handle events from multiple child elements, leveraging event bubbling.

javascript

document.getElementById('parent').addEventListener('click', function(e) {
    if (e.target.matches('button')) {
        console.log('Button clicked:', e.target.id);
    }
});

Benefits: Better performance, works for dynamically added elements.

12. Explain debounce and throttle functions

Answer:
Debounce: Groups multiple calls into one after delay
Throttle: Ensures function is called at most once per specified period

javascript

// Debounce implementation
function debounce(func, delay) {
    let timeout;
    return function(...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), delay);
    };
}

// Throttle implementation
function throttle(func, limit) {
    let inThrottle;
    return function(...args) {
        if (!inThrottle) {
            func.apply(this, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

13. What are generators and how do they work?

Answer: Functions that can be paused and resumed using yield.

javascript

function* numberGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

const gen = numberGenerator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(gen.next().done);  // true

// Use case: Lazy evaluation, infinite sequences
function* infiniteSequence() {
    let i = 0;
    while (true) {
        yield i++;
    }
}

14. Explain the Module Pattern

Answer: A design pattern to create private and public encapsulated code.

javascript

const Module = (function() {
    // Private
    let privateVar = 'secret';
    
    function privateMethod() {
        return privateVar;
    }
    
    // Public
    return {
        publicMethod: function() {
            return privateMethod();
        },
        publicVar: 'accessible'
    };
})();

console.log(Module.publicMethod()); // "secret"
console.log(Module.privateVar);     // undefined

15. What are Web Workers?

Answer: JavaScript running in background threads without blocking the UI.

javascript

// Main thread
const worker = new Worker('worker.js');
worker.postMessage('Hello Worker');
worker.onmessage = (e) => console.log(e.data);

// worker.js
self.onmessage = (e) => {
    const result = heavyComputation(e.data);
    self.postMessage(result);
};

Limitations: No DOM access, communicate via message passing.

ES6+ Modern JavaScript

16. Explain destructuring assignment

Answer: Extract values from arrays or properties from objects into distinct variables.

javascript

// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];

// Object destructuring
const { name, age, ...otherProps } = { 
    name: 'John', 
    age: 30, 
    city: 'NYC' 
};

// Parameter destructuring
function greet({ name, age }) {
    return `Hello ${name}, age ${age}`;
}

// Default values
const { title = 'Default' } = {};

17. What are template literals?

Answer: String literals allowing embedded expressions and multi-line strings.

javascript

const name = 'Alice';
const age = 25;

// Basic usage
const greeting = `Hello, ${name}!`;

// Multi-line
const message = `
    Name: ${name}
    Age: ${age}
    Next year: ${age + 1}
`;

// Tagged templates
function highlight(strings, ...values) {
    return strings.reduce((result, str, i) => 
        `${result}${str}<strong>${values[i] || ''}</strong>`, '');
}

18. Explain spread and rest operators

Answer:
Spread (...): Expands iterables into individual elements

javascript

const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }

// Function arguments
Math.max(...[1, 5, 3]); // 5

Rest (...): Collects multiple elements into an array

javascript

function sum(...numbers) {
    return numbers.reduce((a, b) => a + b);
}
sum(1, 2, 3, 4); // 10

const [first, ...others] = [1, 2, 3, 4];

19. What are Map and Set objects?

Answer:
Map: Key-value pairs with any type as key

javascript

const map = new Map();
map.set('key', 'value');
map.set({}, 'object key');
map.has('key'); // true
map.size; // 2

Set: Collection of unique values

javascript

const set = new Set([1, 2, 3, 3, 2]); // {1, 2, 3}
set.add(4);
set.has(3); // true
set.size; // 4

20. Explain async/await

Answer: Syntactic sugar over promises for asynchronous code.

javascript

async function fetchData() {
    try {
        const response = await fetch('api/data');
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('Error:', error);
        throw error;
    }
}

// Multiple promises
async function fetchAll() {
    const [user, posts] = await Promise.all([
        fetch('/user'),
        fetch('/posts')
    ]);
    return { user, posts };
}

// Async arrow functions
const fetchUser = async (id) => {
    const response = await fetch(`/users/${id}`);
    return response.json();
};

Error Handling & Debugging

21. What are the different error types in JavaScript?

Answer:

javascript

// 1. SyntaxError: Invalid syntax
// const 123abc = 5;

// 2. ReferenceError: Undefined variable
// console.log(undefinedVariable);

// 3. TypeError: Wrong type operation
// null.someMethod();

// 4. RangeError: Invalid range
// new Array(-1);

// 5. URIError: Invalid URI handling
// decodeURI('%');

// 6. AggregateError: Multiple errors (Promise.any)
// 7. Custom errors
class ValidationError extends Error {
    constructor(message) {
        super(message);
        this.name = 'ValidationError';
    }
}

22. How does error handling work with promises?

Answer:

javascript

// Using .catch()
fetch('api/data')
    .then(response => response.json())
    .catch(error => console.error('Fetch failed:', error));

// Using async/await
async function getData() {
    try {
        const response = await fetch('api/data');
        return await response.json();
    } catch (error) {
        // Handle network errors
        throw new Error('Data fetch failed');
    }
}

// Promise-specific methods
Promise.all([p1, p2])  // Fails if any fail
    .catch(error => console.error(error));

Promise.allSettled([p1, p2])  // Always resolves
    .then(results => console.log(results));

23. What is the difference between null and undefined?

Answer:

  • undefined: Variable declared but not assigned, missing property, function without return

  • null: Intentional absence of value, explicitly set by programmer

  • Typeof: typeof undefined → "undefined", typeof null → "object" (historical bug)

  • Usage: null for intentional emptiness, undefined for unintentional missing values

Performance & Optimization

24. How do you measure JavaScript performance?

Answer:

javascript

// 1. Console.time()
console.time('operation');
// Code to measure
console.timeEnd('operation');

// 2. Performance API
const start = performance.now();
// Code to measure
const duration = performance.now() - start;

// 3. Memory usage
console.memory; // Shows heap size

// 4. Chrome DevTools:
// - Performance tab
// - Memory tab
// - Lighthouse audits
// - Coverage tab

// 5. RequestAnimationFrame for animations

25. What is memoization and how to implement it?

Answer: Caching function results for same inputs.

javascript

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;
    };
}

// Example: Fibonacci
const memoizedFib = memoize(function fib(n) {
    if (n <= 1) return n;
    return memoizedFib(n - 1) + memoizedFib(n - 2);
});

DOM & Browser API Questions

26. Explain the event bubbling and capturing phases

Answer:

javascript

// Event flow: Capturing → Target → Bubbling
// Default: Bubbling (inner to outer)

document.querySelector('.outer').addEventListener('click', 
    () => console.log('Bubbling: Outer'), false);

document.querySelector('.inner').addEventListener('click', 
    (e) => {
        console.log('Target: Inner');
        e.stopPropagation(); // Stops bubbling
    }, false);

// Capturing phase (true)
document.querySelector('.outer').addEventListener('click',
    () => console.log('Capturing: Outer'), true);

27. What is the difference between localStorage, sessionStorage, and cookies?

Answer:

Feature localStorage sessionStorage Cookies
Capacity 5-10MB 5-10MB 4KB
Expiration Never Tab close Manual set
Server Access No No Yes (auto-sent)
Scope Origin Origin + Tab Domain/path
API setItem/getItem setItem/getItem document.cookie

28. How does JavaScript handle memory management?

Answer:

  • Automatic garbage collection (mark-and-sweep algorithm)

  • Reference counting (deprecated for circular references)

  • Memory leaks common causes:

    • Global variables

    • Forgotten timers/intervals

    • DOM references in closures

    • Event listeners not removed

    • Circular references

Tools: Chrome DevTools Memory tab, Heap Snapshots

Advanced Topics

29. What are proxies and reflect in JavaScript?

Answer: Proposals for meta-programming.

javascript

// Proxy: Custom behavior for fundamental operations
const handler = {
    get(target, prop) {
        return prop in target ? target[prop] : 'Not found';
    },
    set(target, prop, value) {
        if (prop === 'age' && typeof value !== 'number') {
            throw new Error('Age must be a number');
        }
        target[prop] = value;
        return true;
    }
};

const person = new Proxy({}, handler);
person.age = 30;
console.log(person.name); // "Not found"

// Reflect: Built-in object providing methods for interceptable operations
Reflect.set(person, 'name', 'John');
Reflect.has(person, 'name'); // true

30. Explain the Observer Pattern (or Pub/Sub Pattern)

Answer: A pattern where objects subscribe to events and get notified when events occur.

javascript

class EventEmitter {
    constructor() {
        this.events = {};
    }
    
    on(event, listener) {
        if (!this.events[event]) this.events[event] = [];
        this.events[event].push(listener);
    }
    
    emit(event, ...args) {
        if (this.events[event]) {
            this.events[event].forEach(listener => listener(...args));
        }
    }
    
    off(event, listenerToRemove) {
        if (this.events[event]) {
            this.events[event] = this.events[event]
                .filter(listener => listener !== listenerToRemove);
        }
    }
}

// Usage
const emitter = new EventEmitter();
emitter.on('data', (data) => console.log('Received:', data));
emitter.emit('data', { id: 1 }); // "Received: {id: 1}"

Bonus: Common JavaScript Puzzles

What will this code output?

javascript

console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);

// Output: 1, 4, 3, 2
// Why: Microtasks (promises) run before macrotasks (setTimeout)

Implement a deep clone function

javascript

function deepClone(obj, hash = new WeakMap()) {
    if (obj === null || typeof obj !== 'object') return obj;
    if (hash.has(obj)) return hash.get(obj);
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof RegExp) return new RegExp(obj);
    
    const clone = Array.isArray(obj) ? [] : {};
    hash.set(obj, clone);
    
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            clone[key] = deepClone(obj[key], hash);
        }
    }
    
    return clone;
}

 

Comments (0)

No comments yet. Be the first to comment!

LecturreAI Assistant

Hello! I'm LecturreAI

What would you like to learn today?