Career & Skills

Top 50 JavaScript Interview Questions and Answers for Experienced Candidates

Read the important current affairs of 15 July 2026 for SSC, Banking, UPSC, Railway and all competitive exams.

22 Aug 2024 5 Min Read Quizer Team 407 Views

22

August 2024

JavaScript is one of the most important technologies for modern web development. For experienced developers, JavaScript interviews go beyond basic syntax and often cover closures, prototypes, asynchronous programming, promises, the event loop, browser APIs, performance, security, modules, memory management, and application architecture.

This guide covers 50 important JavaScript interview questions with answers and explanations to help experienced developers prepare for technical interviews.


JavaScript Fundamentals and Advanced Concepts

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

Answer

All three are used to declare variables, but they differ in scope, hoisting behavior, and reassignment.

var a = 10;
let b = 20;
const c = 30;
  • var is function-scoped.

  • let is block-scoped.

  • const is block-scoped.

  • let and const cannot be accessed before their declaration because of the Temporal Dead Zone.

  • A const variable cannot be reassigned.

However, objects declared with const can still be mutated.

const user = { name: "John" };
user.name = "David";

This is valid because the object reference itself was not reassigned.


2. What is hoisting in JavaScript?

Answer

Hoisting is the behavior where JavaScript processes declarations before executing the associated code.

For example:

console.log(a);
var a = 10;

This behaves conceptually like:

var a;
console.log(a);
a = 10;

Therefore, the output is:

undefined

Function declarations are also hoisted:

sayHello();

function sayHello() {
    console.log("Hello");
}

let and const are also created during the environment setup, but accessing them before their declaration results in a ReferenceError because of the Temporal Dead Zone.


3. What is the Temporal Dead Zone (TDZ)?

Answer

The Temporal Dead Zone is the period between entering a scope and the point where a let or const variable is initialized.

console.log(name);

let name = "John";

This throws:

ReferenceError

Explanation

The variable exists in the scope but cannot be accessed before its declaration is evaluated.

Understanding TDZ is important when debugging initialization-related problems.


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

Answer

== performs loose equality comparison and may perform type coercion.

=== performs strict equality comparison without implicit type conversion.

5 == "5";   // true
5 === "5";  // false

Recommendation

In most application code, prefer === because it makes type comparisons explicit and reduces unexpected coercion behavior.


5. What are primitive and reference values in JavaScript?

Answer

JavaScript has primitive types such as:

  • String

  • Number

  • BigInt

  • Boolean

  • Undefined

  • Symbol

  • Null

Objects, arrays, and functions are non-primitive values.

Primitive values are immutable values, while objects are mutable.

Example:

let a = 10;
let b = a;

b = 20;

Changing b does not change a.

With objects:

let user1 = { name: "John" };
let user2 = user1;

user2.name = "David";

Both variables reference the same object, so user1.name also becomes "David".


6. What is a closure in JavaScript?

Answer

A closure occurs when a function retains access to variables from its surrounding lexical scope even after the outer function has finished executing.

function counter() {
    let count = 0;

    return function () {
        count++;
        return count;
    };
}

const increment = counter();

console.log(increment()); // 1
console.log(increment()); // 2

Explanation

The returned function remembers the count variable.

Closures are commonly used for:

  • Data privacy

  • Function factories

  • Callbacks

  • Event handlers

  • Memoization

  • State management


7. What is lexical scope?

Answer

Lexical scope means that the scope of a variable is determined by where the code is written, not where the function is called.

const name = "John";

function greet() {
    console.log(name);
}

greet();

The function can access name because it was defined in an outer lexical scope.

Explanation

Closures are based on lexical scoping.


8. What is the difference between shallow copy and deep copy?

Answer

A shallow copy copies the top-level structure but nested objects can still be shared.

const user = {
    name: "John",
    address: {
        city: "Delhi"
    }
};

const copy = { ...user };

copy.address still refers to the same nested object.

A deep copy creates independent nested structures.

Modern JavaScript provides:

const copy = structuredClone(user);

Explanation

Deep copying is useful when independent nested state is required, but it should not automatically be used everywhere because it can have performance and data-type implications.


9. What is the difference between null and undefined?

Answer

undefined generally means a value has not been assigned or is unavailable.

let value;
console.log(value); // undefined

null is an explicit representation of an intentional absence of a value.

let user = null;

A useful distinction is:

  • undefined → value is not available/assigned.

  • null → application intentionally represents no value.


10. What is the difference between Object.freeze() and Object.seal()?

Answer

Object.freeze() prevents modifications to an object's existing properties and prevents adding or deleting properties.

const user = {
    name: "John"
};

Object.freeze(user);

Object.seal() prevents adding or deleting properties, but existing writable properties can still be changed.

Object.seal(user);

Important

Both are shallow operations. Nested objects are not automatically frozen or sealed.


Functions, Objects and Prototypes

11. What is the prototype chain in JavaScript?

Answer

Objects in JavaScript can inherit properties and methods through their prototype chain.

For example:

const user = {
    name: "John"
};

console.log(user.toString());

toString() is not defined directly on user. JavaScript searches the object's prototype chain to find it.

Explanation

Prototype-based inheritance is fundamental to JavaScript's object model.


12. What is prototypal inheritance?

Answer

Prototypal inheritance allows an object to inherit properties and methods from another object through its prototype.

const person = {
    greet() {
        console.log("Hello");
    }
};

const user = Object.create(person);

user.greet();

The user object can access greet() through its prototype.


13. How do JavaScript classes work internally?

Answer

JavaScript classes provide cleaner syntax for creating objects and working with prototypes.

class User {
    constructor(name) {
        this.name = name;
    }

    greet() {
        return `Hello ${this.name}`;
    }
}

Methods defined on the class are generally placed on the class's prototype.

Therefore, JavaScript classes are a syntax abstraction over JavaScript's prototype-based object model rather than a completely separate inheritance mechanism.


14. What is the difference between regular functions and arrow functions?

Answer

Arrow functions have different behavior for this, arguments, and constructors.

const add = (a, b) => a + b;

Arrow functions do not have their own this. They capture this from the surrounding lexical scope.

Regular functions determine this based on how they are called.

Important

Arrow functions cannot be used with new as constructors.


15. How does this work in JavaScript?

Answer

The value of this depends largely on how a function is called.

const user = {
    name: "John",

    greet() {
        console.log(this.name);
    }
};

user.greet();

Here, this refers to user.

For arrow functions, this is lexically inherited from the surrounding scope.

Interview Tip

Do not explain this simply as "the current object." Its value depends on the invocation context.


16. What are call(), apply(), and bind()?

Answer

They allow explicit control over a function's this value.

call()

Arguments are passed individually.

greet.call(user, "Hello");

apply()

Arguments are passed as an array-like collection.

greet.apply(user, ["Hello"]);

bind()

Returns a new function with this bound.

const fn = greet.bind(user);
fn();

17. What is currying in JavaScript?

Answer

Currying transforms a function with multiple arguments into a sequence of functions that each accept fewer arguments.

function add(a) {
    return function (b) {
        return function (c) {
            return a + b + c;
        };
    };
}

console.log(add(2)(3)(4)); // 9

Currying can be useful for function composition and reusable operations.


18. What is memoization?

Answer

Memoization is an optimization technique where the result of an expensive function is cached so that repeated calls with the same input can reuse the result.

function memoize(fn) {
    const cache = new Map();

    return function (value) {
        if (cache.has(value)) {
            return cache.get(value);
        }

        const result = fn(value);
        cache.set(value, result);

        return result;
    };
}

Common Uses

  • Expensive calculations

  • Recursive algorithms

  • Repeated API-independent computations

  • Derived application state


Asynchronous JavaScript

19. What is the JavaScript event loop?

Answer

JavaScript executes synchronous code on the call stack. Asynchronous operations are handled through the host environment, and their callbacks are scheduled for execution when the stack becomes available.

A simplified model involves:

Call Stack
    ↓
Host APIs
    ↓
Task/Microtask Queues
    ↓
Event Loop
    ↓
Call Stack

Explanation

The event loop enables JavaScript to handle asynchronous operations without blocking the main execution thread for every operation.


20. What is the difference between microtasks and macrotasks?

Answer

Examples of microtasks include:

  • Promise callbacks

  • queueMicrotask()

Examples of tasks/macrotasks include:

  • setTimeout()

  • setInterval()

  • Certain browser events

Consider:

console.log("A");

setTimeout(() => console.log("B"), 0);

Promise.resolve().then(() => console.log("C"));

console.log("D");

The output is:

A
D
C
B

Explanation

After the synchronous code completes, microtasks are generally processed before the next task is taken from the task queue.


21. What are Promises in JavaScript?

Answer

A Promise represents the eventual completion or failure of an asynchronous operation.

It has three conceptual states:

  • Pending

  • Fulfilled

  • Rejected

Example:

const promise = fetch("/api/users");

promise
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));

Promises make asynchronous code easier to compose than deeply nested callbacks.


22. What is async/await?

Answer

async/await provides syntax for working with Promises in a more synchronous-looking style.

async function getUsers() {
    try {
        const response = await fetch("/api/users");
        const data = await response.json();

        return data;
    } catch (error) {
        console.error(error);
    }
}

An async function always returns a Promise.

Important

await does not block the entire JavaScript runtime. It pauses the execution of that async function until the awaited Promise settles.


23. What is the difference between Promise.all() and Promise.allSettled()?

Answer

Promise.all() rejects as soon as one of its input Promises rejects.

const results = await Promise.all([
    fetchUsers(),
    fetchProducts(),
    fetchOrders()
]);

It is useful when all operations are required for successful completion.

Promise.allSettled() waits for every Promise and reports each outcome.

const results = await Promise.allSettled([
    fetchUsers(),
    fetchProducts(),
    fetchOrders()
]);

This is useful when you want to process successful and failed operations independently.


24. What is the difference between Promise.race() and Promise.any()?

Answer

Promise.race() settles when the first input Promise settles, whether fulfilled or rejected.

Promise.any() fulfills when the first input Promise fulfills. It rejects only when all input Promises reject.

Example use cases:

  • race() → timeout behavior or first-settled operation

  • any() → try multiple independent sources and accept the first successful response


25. How do you handle errors in asynchronous JavaScript?

Answer

With async/await, use try/catch.

async function loadData() {
    try {
        const response = await fetch("/api/data");

        if (!response.ok) {
            throw new Error(`HTTP error: ${response.status}`);
        }

        return await response.json();
    } catch (error) {
        console.error(error);
    }
}

Explanation

A robust application should distinguish between:

  • Network failures

  • HTTP errors

  • Validation errors

  • Authentication failures

  • Unexpected application errors


26. What is callback hell?

Answer

Callback hell occurs when asynchronous callbacks become deeply nested and difficult to maintain.

Example:

getUser(function (user) {
    getOrders(user.id, function (orders) {
        getPayment(orders[0], function (payment) {
            // More nested logic
        });
    });
});

Promises and async/await can make such workflows easier to read and maintain.


Browser and DOM

27. What is event delegation?

Answer

Event delegation involves placing an event listener on a parent element instead of attaching separate listeners to every child.

document.querySelector("#users").addEventListener("click", function (event) {
    if (event.target.matches(".delete")) {
        console.log("Delete clicked");
    }
});

Benefits

  • Fewer event listeners

  • Better handling of dynamically created elements

  • Potentially lower memory overhead

  • Centralized event handling


28. What is event bubbling and event capturing?

Answer

DOM events can travel through the document in phases.

A simplified model is:

Capturing
    ↓
Target
    ↓
Bubbling

By default, many event listeners operate during the bubbling phase.

You can listen during capturing:

element.addEventListener("click", handler, true);

Understanding propagation is important when debugging complex UI interactions.


29. What is the difference between preventDefault() and stopPropagation()?

Answer

preventDefault() prevents the browser's default action.

event.preventDefault();

For example, it can prevent a link from navigating.

stopPropagation() stops the event from continuing through its propagation path.

event.stopPropagation();

They solve different problems and should not be treated as interchangeable.


30. What is the difference between DOMContentLoaded and load?

Answer

DOMContentLoaded fires when the HTML document has been parsed and the DOM is ready.

document.addEventListener("DOMContentLoaded", () => {
    // DOM is ready
});

load fires after the page and its dependent resources, such as images, have finished loading.

For DOM initialization, DOMContentLoaded is often the more appropriate event.


Performance and Memory

31. How can you improve JavaScript application performance?

Answer

Common approaches include:

  • Reduce unnecessary JavaScript

  • Code splitting

  • Lazy loading

  • Minification and compression

  • Efficient DOM updates

  • Debouncing expensive events

  • Avoiding unnecessary network requests

  • Caching appropriate data

  • Reducing bundle size

  • Using Web Workers for suitable CPU-heavy tasks

  • Profiling before optimizing

Important

Do not optimize based only on assumptions. Use browser performance tools and real measurements.


32. What is debouncing?

Answer

Debouncing ensures that a function runs only after a specified period has passed without another invocation.

function debounce(fn, delay) {
    let timer;

    return function (...args) {
        clearTimeout(timer);

        timer = setTimeout(() => {
            fn.apply(this, args);
        }, delay);
    };
}

Common Uses

  • Search boxes

  • Window resizing

  • Form validation

  • Autocomplete


33. What is throttling?

Answer

Throttling limits how frequently a function can execute.

It is useful for high-frequency events such as:

  • Scroll

  • Mouse movement

  • Resize

  • Pointer events

Difference

Debounce: Wait until activity stops.

Throttle: Execute at controlled intervals during activity.


34. What causes memory leaks in JavaScript?

Answer

A memory leak occurs when memory that is no longer needed remains reachable and therefore cannot be reclaimed.

Common causes include:

  • Unremoved event listeners

  • Long-lived timers

  • Unnecessary global references

  • Detached DOM nodes still referenced by JavaScript

  • Growing caches

  • Closures retaining unnecessary objects

Example

const cache = new Map();

function storeData(key, data) {
    cache.set(key, data);
}

If the cache grows indefinitely, it can consume significant memory.


35. What is garbage collection in JavaScript?

Answer

JavaScript engines automatically reclaim memory that is no longer reachable by the running program.

Modern engines commonly use tracing garbage collection techniques.

Developers generally do not manually free memory. Instead, they should ensure that unnecessary objects are no longer referenced.


Modern JavaScript

36. What are ES modules?

Answer

ES modules provide a standardized way to organize JavaScript code using import and export.

// user.js
export function getUser() {
    // ...
}

Then:

import { getUser } from "./user.js";

Benefits

  • Better code organization

  • Explicit dependencies

  • Reusability

  • Easier static analysis

  • Support for tree-shaking in build systems


37. What is dynamic import()?

Answer

Dynamic import loads a module asynchronously at runtime.

const module = await import("./reports.js");

This can be useful for:

  • Lazy loading

  • Code splitting

  • Feature-based loading

  • Reducing initial JavaScript payload


38. What is optional chaining?

Answer

Optional chaining allows safe access to nested properties.

const city = user?.address?.city;

If user or address is null or undefined, the expression returns undefined instead of throwing an error.


39. What is the nullish coalescing operator?

Answer

The ?? operator provides a fallback only when the left-hand value is null or undefined.

const name = user.name ?? "Guest";

This differs from ||.

const count = 0 || 10;   // 10
const count2 = 0 ?? 10;  // 0

This distinction is important when values such as 0, false, or an empty string are valid.


40. What are generators in JavaScript?

Answer

Generators are functions that can pause and resume execution.

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

const generator = numbers();

console.log(generator.next());
console.log(generator.next());

Generators return iterator objects and can be useful for:

  • Lazy sequences

  • Iteration

  • Streaming-style processing

  • Custom iteration behavior


APIs, Security and Architecture

41. What is CORS?

Answer

CORS, or Cross-Origin Resource Sharing, is a browser security mechanism that controls whether a web page can access resources from another origin.

A server can explicitly allow origins through HTTP response headers.

For example:

Access-Control-Allow-Origin

Important

CORS is primarily enforced by browsers. It is not a substitute for authentication or authorization.


42. How can you prevent XSS attacks in JavaScript applications?

Answer

Cross-Site Scripting (XSS) occurs when untrusted content is interpreted as executable HTML or script.

Important defenses include:

  • Escape untrusted output

  • Prefer textContent for plain text

  • Avoid unsafe use of innerHTML

  • Sanitize HTML when HTML input is genuinely required

  • Use Content Security Policy where appropriate

  • Validate input on the server

  • Use secure cookie attributes

Example:

element.textContent = userInput;

This is generally safer than directly inserting untrusted input as HTML.


43. How should sensitive data be handled in frontend JavaScript?

Answer

Sensitive information should not be considered secret simply because it is hidden in frontend code.

Never hard-code:

  • Database passwords

  • Private API keys

  • Secret tokens

  • Server credentials

Frontend JavaScript is delivered to the client and can be inspected.

Sensitive operations should be performed on trusted backend systems.


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

Answer

localStorage

Data persists across browser sessions until removed.

localStorage.setItem("theme", "dark");

sessionStorage

Data generally lasts for the lifetime of the page session.

sessionStorage.setItem("step", "2");

Cookies

Cookies can be sent to the server with requests depending on their attributes.

For authentication-related cookies, security attributes such as:

  • HttpOnly

  • Secure

  • SameSite

are important.

Interview Tip

Do not automatically recommend localStorage for authentication tokens without discussing the application's threat model, especially XSS risk.


45. How does fetch() work?

Answer

fetch() provides a Promise-based API for making network requests.

async function getUsers() {
    const response = await fetch("/api/users");

    if (!response.ok) {
        throw new Error("Request failed");
    }

    return response.json();
}

Important

fetch() does not automatically reject its Promise for HTTP error status codes such as 404 or 500. You should check response.ok or response.status.


Advanced JavaScript and System Design

46. How would you design a scalable frontend JavaScript application?

Answer

A scalable frontend should have clear separation of concerns.

A possible structure is:

Application
│
├── Components
├── Services
├── State
├── Utilities
├── API Layer
├── Routing
└── Shared Modules

Important considerations include:

  • Modular architecture

  • Clear state ownership

  • Reusable components

  • API abstraction

  • Error handling

  • Lazy loading

  • Code splitting

  • Testing

  • Performance monitoring

  • Consistent coding standards

The architecture should be appropriate for the application's size rather than introducing unnecessary complexity.


47. How would you debug a slow JavaScript application?

Answer

I would first reproduce and measure the problem.

A practical process is:

  1. Check browser Performance tools.

  2. Identify long-running JavaScript tasks.

  3. Check network requests.

  4. Analyze bundle size.

  5. Look for unnecessary rendering.

  6. Check memory usage.

  7. Identify expensive loops or calculations.

  8. Review event listeners.

  9. Check API response times.

  10. Measure improvements after each change.

Key Principle

Measure → identify bottleneck → optimize → measure again.


48. How would you prevent duplicate API requests?

Answer

The approach depends on the application.

Possible strategies include:

  • Debouncing user input

  • Request caching

  • Request deduplication

  • Aborting obsolete requests

  • Tracking requests already in progress

  • Client-side state management

For example, when implementing search autocomplete, AbortController can cancel an outdated request:

const controller = new AbortController();

fetch("/api/search?q=javascript", {
    signal: controller.signal
});

// Cancel request
controller.abort();

This prevents outdated requests from unnecessarily consuming resources.


49. What is AbortController and where can it be used?

Answer

AbortController provides a standard way to signal cancellation to APIs that support abort signals.

Example:

const controller = new AbortController();

fetch("/api/users", {
    signal: controller.signal
})
.then(response => response.json())
.catch(error => {
    if (error.name === "AbortError") {
        console.log("Request cancelled");
    }
});

controller.abort();

Common Uses

  • Canceling fetch requests

  • Search/autocomplete

  • Component cleanup

  • Preventing outdated requests

  • Canceling long-running supported operations


50. What are the most important principles for writing production-quality JavaScript?

Answer

Production-quality JavaScript should focus on:

  • Readability

  • Maintainability

  • Correctness

  • Security

  • Performance

  • Testability

  • Error handling

  • Modularity

  • Accessibility

  • Observability

A senior developer should also consider:

Requirements
     ↓
Architecture
     ↓
Implementation
     ↓
Testing
     ↓
Performance
     ↓
Security
     ↓
Monitoring
     ↓
Maintenance

Explanation

Experienced developers are expected to think beyond whether the code simply works.

They should consider:

  • What happens when the API fails?

  • What happens with thousands of users?

  • What happens on a slow network?

  • Can the code be maintained by another developer?

  • Could untrusted input create a security issue?

  • Can unnecessary work be avoided?

  • How will production problems be diagnosed?

These considerations distinguish basic JavaScript knowledge from production-level engineering.


Quick Revision: 50 JavaScript Interview Topics

Before an experienced-level JavaScript interview, revise these topics:

  1. var, let, and const

  2. Hoisting

  3. Temporal Dead Zone

  4. == vs ===

  5. Primitive and reference values

  6. Shallow vs deep copy

  7. null vs undefined

  8. Object.freeze() vs Object.seal()

  9. Closures

  10. Lexical scope

  11. Prototype chain

  12. Prototypal inheritance

  13. JavaScript classes

  14. Arrow functions

  15. this

  16. call(), apply(), bind()

  17. Currying

  18. Memoization

  19. Event loop

  20. Microtasks and tasks

  21. Promises

  22. async/await

  23. Promise.all()

  24. Promise.allSettled()

  25. Promise.race()

  26. Promise.any()

  27. Error handling

  28. Event delegation

  29. Event bubbling/capturing

  30. preventDefault() vs stopPropagation()

  31. DOMContentLoaded vs load

  32. JavaScript performance

  33. Debouncing

  34. Throttling

  35. Memory leaks

  36. Garbage collection

  37. ES modules

  38. Dynamic imports

  39. Optional chaining

  40. Nullish coalescing

  41. Generators

  42. CORS

  43. XSS prevention

  44. Frontend security

  45. Storage mechanisms

  46. Fetch API

  47. Frontend architecture

  48. Debugging performance

  49. Request cancellation

  50. Production-quality JavaScript

Final Interview Tip

For experienced JavaScript candidates, interviewers often evaluate how you think, not just whether you remember JavaScript syntax.

When answering advanced questions, try to explain:

Concept → Practical example → Trade-off → Real-world use case

For example, when discussing caching, don't stop at explaining what caching is. Explain what you would cache, how you would invalidate it, what could go wrong, and how you would measure whether it actually improves performance.

This approach demonstrates practical engineering experience rather than memorized knowledge.

Why This Content Matters

This content is prepared to help students and competitive-exam aspirants understand important topics, revise key information, and strengthen their exam preparation.

  • Quickly revise important facts and concepts
  • Improve General Knowledge and exam awareness
  • Support preparation for competitive and government exams
  • Build a consistent and effective study routine
Quizer Team
About the Author

Quizer Team

The Quizer Team creates exam-focused educational content, current affairs, general knowledge, study notes, and preparation resources to help students and competitive-exam aspirants learn, practice, and stay updated.

Educational Content Exam Focused Learning Resources

📢 Join Our WhatsApp Channel

Get Daily GK, Current Affairs, Amazing Facts & Quiz Updates.

🚀 Join Now

Join Monthly Challenge

Compete, Learn & Win exciting prizes.

  • Cash Rewards
  • E-Certificates
  • Leaderboard Ranking
  • Daily Practice
Join Now

Related Post

Career & Skills
29 Aug 2025 120
Read More
Career & Skills
4 Jun 2025 133
Read More
Career & Skills
22 Aug 2024 361
Read More