JavaScript Interview QnA
JavaScript Interview QnA
Interview Q&A
Web Development · DOM · Events · Async · ES6+ · OOP in JS
5–6 LPA · Entry Level · Frontend / Full-Stack Web Dev Prep
Core JS · DOM · Events · Async · OOP · APIs · Browser StorageModel Answers Follow-ups Answered
How to use: Questions go Easy → Medium → Hard. Every question has a full Model Answer. Blue boxes = follow-up
questions with full answers. Green boxes = deeper probes. This guide covers JavaScript from the perspective of web
development — DOM manipulation, events, async patterns, ES6+, and browser APIs. OOP theory is covered in the
Python guide; here we focus on JS-specific OOP (prototypes, classes).
■ Section 1: JavaScript Fundamentals — Types, Scope & Hoisting
■ Model Answer:
JavaScript is a dynamically typed, single-threaded, interpreted scripting language. It is the only language natively
supported by browsers, making it essential for web interactivity. In the browser: the JS engine (V8 in Chrome,
SpiderMonkey in Firefox) parses and executes JS. JS runs in a single thread — one task at a time — but handles
concurrency via the Event Loop (callbacks, Promises, async/await). Beyond browsers: [Link] runs JS on the server
using V8.
[Link]("4 - sync");
// Output order: 1, 4, 3, 2
// Sync first, then microtasks (Promise), then macro tasks (setTimeout)
■ Model Answer:
var: function-scoped, hoisted and INITIALISED to undefined at the top of its function. Can be re-declared. Avoid in
modern JS. let: block-scoped ({}), hoisted but NOT initialised — accessing before declaration throws ReferenceError
(Temporal Dead Zone). Cannot be re-declared. const: block-scoped, same as let but MUST be assigned at declaration
and cannot be reassigned. The binding is const, not the value — object properties can still be mutated. Hoisting: JS
moves declarations to the top of their scope at compile time. var declarations hoist with undefined; function declarations
hoist fully.
// var — function scoped, hoisted
function example() {
[Link](x); // undefined (hoisted)
var x = 10;
[Link](x); // 10
}
Q3. What is the difference between == and ===? Explain type coercion.
■ Topic: Type Coercion
● Easy — must answer cold
■ Model Answer:
=== (strict equality): checks VALUE and TYPE — no coercion. Always use this. == (loose equality): checks value after
TYPE COERCION — JS converts one or both operands to a common type using complex rules. Type coercion: JS
automatically converts types in certain operations. "5" + 3 = "53" (string concatenation). "5" - 3 = 2 (numeric). Falsy
values: false, 0, "", null, undefined, NaN — all coerce to false in boolean context. Everything else is truthy.
// === vs == — always use ===
5 === "5" // false — different types
5 == "5" // true — "5" coerced to number
null == undefined // true — special case
null === undefined // false
// Falsy values
const falsy = [false, 0, "", null, undefined, NaN];
[Link](v => !v); // true — all falsy
// Safe checks
[Link](NaN) // true
[Link]("hello") // false (no coercion)
isNaN("hello") // true (coerces!) — avoid
// Explicit conversion
Number("42") // 42
String(42) // "42"
Boolean(0) // false
Boolean("hi") // true
■ Model Answer:
A closure is a function that retains access to variables from its outer (enclosing) scope even after that outer function has
returned. In JS, every function creates a closure over the variables in scope when it was defined. The inner function
"closes over" the outer variables — they are kept alive in memory as long as the inner function exists. Use cases: data
privacy/encapsulation, factory functions, event handlers that remember context, memoization, module pattern.
// Closure — factory function
function makeCounter(start = 0) {
let count = start; // private to this call
return {
increment() { return ++count; },
decrement() { return --count; },
reset() { count = start; },
value() { return count; }
};
}
const c1 = makeCounter(10);
const c2 = makeCounter(0);
[Link](); // 11
[Link](); // 1 — independent closures
■ Follow-up: What is the module pattern and how does it use closures?
The module pattern uses closures to create private state — variables that are inaccessible from outside but
remembered by the returned public API. const counter = (function() { let count = 0; return { increment() { count++; },
decrement() { count--; }, getCount() { return count; } }; })(); count is private — outside code cannot access it directly.
Only the returned methods can access it via closure. This was how JS modules worked before ES6 import/export.
Today, ES modules have file-level scope which provides similar privacy.
■ Model Answer:
"this" refers to the execution context — the object that is currently calling the function. Its value depends entirely on HOW
the function is called, not where it is defined. Global context: this = window (browser) or global ([Link]). Object method:
this = the object before the dot. Constructor (new): this = the newly created object. Arrow function: NO own this — inherits
this from the enclosing lexical scope. Explicit: call(thisArg), apply(thisArg, [args]), bind(thisArg) — set this manually.
// this depends on call site, not definition
const obj = {
name: "Alice",
greet() { return `Hi, ${[Link]}`; },
greetArrow: () => `Hi, ${this?.name}`, // this = outer scope
};
■ Model Answer:
Destructuring: extract values from arrays or properties from objects into named variables — clean, concise alternative to
multiple assignment statements. Spread (...): expands an iterable (array, string) or object into individual elements. Rest
(...): collects remaining elements into an array (in function params or destructuring). These three features work together
and are fundamental to modern JS style.
// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];
// first=1, second=2, rest=[3,4,5]
// Swap variables
let a = 1, b = 2;
[a, b] = [b, a]; // a=2, b=1
// Rest in function
function sum(first, ...rest) {
return first + [Link]((acc, n) => acc + n, 0);
}
sum(1, 2, 3, 4); // 10
■ Model Answer:
Template literals: backtick strings that allow embedded expressions ${} and multi-line strings without \n. Tagged
templates: a function before the template literal — the function receives the string parts and interpolated values
separately, enabling custom string processing. Used in: styled-components (CSS-in-JS), GraphQL query strings (gql),
SQL query builders, i18n libraries.
// Template literal — multi-line and expressions
const product = { name: "Laptop", price: 75000, discount: 10 };
const html = `
${[Link]}
Price: ■${([Link] * (1 - [Link]/100)).toFixed(2)}
`;
■ Follow-up: What are some practical uses of template literals in web development?
Dynamic HTML generation: const card = `${[Link]}${[Link]}`. Multi-line SQL (though use parameterized
queries, not string interpolation for user data!). CSS-in-JS with styled-components: const Button =
[Link]`background: ${props => [Link] ? "blue" : "white"}`. Logging: [Link](`User ${[Link]}
performed ${action} at ${new Date().toISOString()}`).
■ Model Answer:
ES6 modules allow splitting code into separate files with explicit imports and exports. Each module has its own scope —
variables are NOT global by default. Named export: export const PI = 3.14; — import { PI } from "./[Link]". Multiple per
file. Default export: export default class App {} — import App from "./[Link]". One per file. In HTML: use script tag with
type="module" — enables import/export in the browser. Modules are deferred by default.
// [Link] — named exports
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export class Vector { constructor(x,y){this.x=x;this.y=y;} }
// [Link] — importing
import formatCurrency from "./[Link]"; // default
import { PI, add, Vector } from "./[Link]"; // named
import * as MathUtils from "./[Link]"; // namespace
import { add as sum } from "./[Link]"; // rename
■ Follow-up: What is the difference between CommonJS (require) and ES Modules (import)?
CommonJS ([Link], older): const express = require("express"). Synchronous, loads at runtime, dynamic (can require
conditionally). ES Modules: import express from "express". Static — imports are resolved at parse time, enabling
tree-shaking (bundlers can remove unused exports). Asynchronous-capable. In [Link]: use .mjs extension or
"type":"module" in [Link] for ES modules. In browsers: only ES modules are natively supported (CommonJS
requires a bundler like webpack/vite). Dynamic import(): const module = await import("./[Link]") — lazy-load ES
modules on demand.
Q9. What is the DOM? How do you select and manipulate elements?
■ Topic: DOM
● Easy — must answer cold
■ Model Answer:
The DOM (Document Object Model) is the browser's tree-like in-memory representation of the HTML document. JS
interacts with the page by reading and modifying DOM nodes. Selecting elements: [Link],
[Link] (CSS selector, returns first match), [Link] (returns NodeList of all
matches). Modifying: [Link], [Link], [Link], [Link], [Link].
// Selecting elements
const title = [Link]("title");
const btn = [Link](".submit-btn");
const cards = [Link](".product-card");
// Styling
[Link] = "blue";
[Link] = "color:white; padding:8px 16px;";
// Attributes
[Link]("data-product-id", "42");
[Link]("data-product-id"); // "42"
[Link]; // "42" (data- attributes)
Q10. How do you traverse the DOM? Explain parent, child, and sibling relationships.
■ Topic: DOM Traversal
● Easy — must answer cold
■ Model Answer:
Every DOM node has properties to navigate the tree. Parent: [Link]. Children: [Link]
(HTMLCollection, element nodes only), [Link] (NodeList, includes text nodes). First/Last child:
[Link], [Link]. Siblings: [Link],
[Link]. Closest ancestor matching selector: [Link](".container") — walks up the
DOM.
const list = [Link](".product-list");
// Children
[Link]; // HTMLCollection of li elements
[Link][0]; // first li
[Link]; // first li
[Link]; // last li
[Link]; // count
// Parent
const item = [Link](".product-list li");
[Link]; // the ul
[Link]; // grandparent
// Siblings
[Link]; // next li
[Link];// previous li
Q11. What is event delegation? Why is it better than attaching listeners to each
element?
■ Topic: Events & DOM
● Medium — should know well
■ Model Answer:
Event delegation: attach ONE event listener to a PARENT element instead of separate listeners on each child. Relies on
event bubbling — events bubble up from the target to the root. Check [Link] inside the handler to know which child
was clicked. Advantages: (1) Memory efficient — one listener vs hundreds. (2) Works for dynamically added elements —
no need to re-attach listeners. (3) Less code.
// WITHOUT delegation — attach to each item (bad)
[Link](".product-card .delete-btn").forEach(btn => {
[Link]("click", handleDelete); // N listeners, dynamic elements missed
});
Q12. How do you make HTTP requests in JavaScript? Explain fetch() and
async/await.
■ Topic: Browser APIs / Async
● Medium — should know well
■ Model Answer:
fetch(url, options): browser-native API for HTTP requests. Returns a Promise that resolves to a Response object.
Two-step: first await fetch() to get the response, then await [Link]() (or .text(), .blob()) to read the body. Always
check [Link] (status 200-299) — fetch only rejects on network failure, NOT on 4xx/5xx status codes.
// fetch with async/await — correct pattern
async function getProducts(page = 1) {
try {
const res = await fetch(`/api/products?page=${page}`, {
method: "GET",
headers: { "Authorization": `Bearer ${token}` }
});
if (![Link]) {
throw new Error(`Server error: ${[Link]}`);
}
■ Model Answer:
Every JS object has an internal link to another object called its prototype ([[Prototype]] or __proto__). When you access a
property, JS first checks the object itself, then its prototype, then the prototype's prototype — up the prototype chain until
null. All objects created with object literals inherit from [Link]. Functions have a .prototype property — when
used with "new", the created object's [[Prototype]] is set to the function's .prototype.
// Prototype chain
const animal = { breathe() { return "breathing"; } };
const dog = [Link](animal); // dog.__proto__ === animal
[Link] = function() { return "woof"; };
Q14. What are getters, setters, and private class fields in JavaScript?
■ Topic: JS OOP / Classes
● Medium — should know well
■ Model Answer:
Getters/Setters: get and set keywords define computed properties on a class — accessed like attributes but run code.
Private fields (#): declared with # prefix — truly private to the class, NOT accessible outside (unlike _ convention which is
just a convention). Static members: belong to the class itself, not instances — class-level utility methods and constants.
class Product {
#price; // private field — truly private
#stock;
■ Follow-up: How are private class fields (#) different from the _ convention?
_ prefix (convention): no enforcement — _privateVar is accessible by anyone. Just a signal to other developers: "don't
use this directly." # private fields (ES2022): enforced by the language engine — access from outside throws
SyntaxError. [Link](person.#name) from outside the class — SyntaxError. # fields must be declared in the class
body before use (unlike this.x which can be created in constructor). You can check if a private field exists: #name in obj
(within the class). Private methods: #doSomething() {} — same syntax.
// Creating a Promise
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Promise chaining
fetch("/api/user/1")
.then(res => {
if (![Link]) throw new Error(`${[Link]}`);
return [Link](); // return Promise — chain waits
})
.then(user => fetch(`/api/orders?userId=${[Link]}`))
.then(res => [Link]())
.then(orders => renderOrders(orders))
.catch(err => showError([Link]))
.finally(() => hideSpinner()); // always runs
■ Follow-up: What is Promise chaining and what is the "callback hell" it solves?
Callback hell: deeply nested callbacks, hard to read and error-handle: getData(function(a){ getMoreData(a, function(b){
getEvenMore(b, function(c){...})})}). Promise chaining: flat, readable:
fetch(url).then(r=>[Link]()).then(data=>process(data)).catch(handleError). Each .then() returns a new Promise — if you
return a value, it wraps it in a resolved Promise. If you return a Promise, the chain waits for it. async/await makes this
even more readable: const data = await (await fetch(url)).json().
Q16. Explain async/await. How do you run multiple async operations concurrently?
■ Topic: Async / Await
● Medium — should know well
■ Model Answer:
async function: always returns a Promise. await expression: pauses the async function until the awaited Promise settles.
Does NOT block the thread — the event loop processes other tasks while waiting. Must be inside an async function (or
top-level module). Error handling: wrap in try/catch — cleaner than .catch() chains for sequential logic.
// WRONG — sequential (slow)
async function loadPageData() {
const user = await getUser(); // waits for user
const products = await getProducts(); // then waits for products
const cart = await getCart(); // then cart — total: t1+t2+t3
return { user, products, cart };
}
■ Follow-up: How do you handle errors for multiple independent async operations?
If using [Link] and one fails, the whole thing rejects — you lose all results. Use [Link]: const results =
await [Link]([op1(), op2(), op3()]); Then filter: const succeeded = [Link](r => [Link] ===
"fulfilled").map(r => [Link]); Or wrap each individual operation: const safe = async (p) => { try { return {ok:true, value:
await p} } catch(e) { return {ok:false, error:e} } }; await [Link]([op1, op2].map(safe));
Q17. What are the browser storage options? Compare localStorage, sessionStorage,
and cookies.
■ Topic: Browser Storage
● Easy — must answer cold
■ Model Answer:
localStorage: stores key-value strings persistently — survives browser close. Same origin only. ~5MB. sessionStorage:
same API but cleared when the TAB is closed. Not shared across tabs. Cookies: server-readable, sent with every HTTP
request to the matching domain. Can set expiry, HttpOnly (no JS access), Secure (HTTPS only), SameSite. ~4KB.
IndexedDB: full database in the browser — structured data, large storage, async API.
// localStorage — persist cart across sessions
const CART_KEY = "shopping_cart";
function saveCart(cart) {
try {
[Link](CART_KEY, [Link](cart));
} catch (e) {
[Link]("Storage quota exceeded:", e);
}
}
function loadCart() {
const raw = [Link](CART_KEY);
return raw ? [Link](raw) : [];
}
■ Follow-up: When should you use localStorage vs cookies for auth tokens?
Never store sensitive auth tokens in localStorage — any XSS attack can read it: [Link] or
[Link](). Store auth tokens in HttpOnly cookies — JavaScript cannot read them, even during XSS. JWT
access token: can store in memory (JS variable) — lost on page refresh but safe. Refresh token: store in HttpOnly,
Secure, SameSite=Strict cookie — server sets it, JS never sees it. localStorage is fine for: theme preference, UI state,
shopping cart (non-sensitive), language preference.
■ Follow-up: What is the Web Storage API and how do you use it correctly?
[Link]("key", value): value MUST be a string — store objects with [Link].
[Link]("key"): returns string or null — parse with [Link]. [Link]("key"): remove
one item. [Link](): remove all items for this origin. Storage quota: ~5–10MB depending on browser.
Exceeding throws QuotaExceededError — always wrap in try/catch. Storage event: fires in other tabs/windows when
localStorage changes — enables cross-tab sync.
Q18. How do you handle forms in JavaScript? Explain validation and FormData.
■ Topic: Forms & DOM
● Medium — should know well
■ Model Answer:
Form handling: listen to the submit event, call [Link]() to stop page reload, then read values and validate, then
submit via fetch. FormData API: creates key-value pairs from a form — handles text, files, checkboxes automatically.
HTML5 validation attributes: required, minlength, maxlength, pattern, type="email". Custom validation:
[Link](message) and the invalid event.
const form = [Link]("#checkout-form");
try {
const res = await fetch("/api/checkout/", {
method: "POST",
headers: { "Authorization": `Bearer ${token}` },
body: fd // NO Content-Type header — fetch sets it
});
if (![Link]) throw new Error(await [Link]());
[Link] = "/order-success";
} catch (err) {
showError("Submission failed: " + [Link]);
}
});
function validateForm(form) {
const errors = [];
const email = [Link]();
if (!email) [Link]("Email is required");
else if (!/^[^@]+@[^@]+\.[^@]+$/.test(email))
[Link]("Invalid email format");
return errors;
}
■ Model Answer:
Intersection Observer: efficiently detects when an element enters or exits the viewport (or another element). Replaces the
old pattern of listening to scroll events + getBoundingClientRect() — which is expensive (causes layout reflow on every
scroll). IO uses the browser's rendering thread — no layout reflow, no main thread blocking. Use cases: lazy loading
images, infinite scroll, animating elements on scroll-in, tracking ad visibility.
// Animate on scroll-in
const animObserver = new IntersectionObserver((entries) => {
[Link](({ target, isIntersecting }) => {
[Link]("visible", isIntersecting);
});
}, { threshold: 0.1 });
[Link](".animate-on-scroll")
.forEach(el => [Link](el));
■ Follow-up: How do you implement lazy loading images with Intersection Observer?
Store real image URLs in data-src attribute. Set src to a placeholder. const observer = new
IntersectionObserver((entries, obs) => { [Link](entry => { if ([Link]) { [Link] =
[Link]; [Link]([Link]); } }); }); [Link]("img[data-src]").forEach(img
=> [Link](img)); When the image scrolls into view, set src from data-src and stop observing it. Modern
HTML also has loading="lazy" attribute — browser-native lazy loading without JS.
■ Model Answer:
Debouncing: delays execution until AFTER a pause in events. If the event fires again before the delay, the timer resets.
Use for: search-as-you-type (wait until user stops typing), window resize handler, form validation on input. Throttling:
allows execution at most ONCE per time interval — guarantees regular execution. Use for: scroll events, mouse move,
game loop, rate-limiting API calls.
[Link]("scroll",
throttle(() => updateScrollProgress(), 100)
);
Q21. What is the difference between synchronous and asynchronous code? What is
a callback?
■ Topic: Async Fundamentals
● Easy — must answer cold
■ Model Answer:
Synchronous: code executes line by line — each line waits for the previous to complete. Blocks the thread.
Asynchronous: operations are started and the program continues — a callback is registered to handle the result when
ready. Callback: a function passed as an argument to another function, to be called later when an async operation
completes. Callbacks are the original async mechanism in JS — later replaced by Promises, then async/await.
Q22. What is CORS? How does the browser enforce it and how do you fix CORS
errors?
■ Topic: Web Security
● Medium — should know well
■ Model Answer:
CORS (Cross-Origin Resource Sharing): a browser security mechanism that restricts web pages from making requests to
a DIFFERENT origin (protocol + domain + port). The browser sends an Origin header. The server must respond with
Access-Control-Allow-Origin matching that origin (or *). Without this header: browser blocks the response — CORS error.
The request WAS sent and processed — just the response is blocked. For complex requests (non-GET, custom
headers): browser sends a preflight OPTIONS request first.
// CORS error in browser console:
// "Access to fetch at "[Link] from origin
// "[Link] has been blocked by CORS policy"
■ Follow-up: Why does CORS only affect browsers and not curl or Postman?
CORS is enforced by the BROWSER — it's a browser security feature protecting users. curl, Postman,
server-to-server calls have no browser — no CORS enforcement. This is why your Django API might work perfectly in
Postman but fail in the browser. It's also why CORS is not a complete security measure — it only prevents cross-origin
browser requests from accessing responses. Fix CORS in Django: install django-cors-headers. Add to
INSTALLED_APPS, MIDDLEWARE, and set CORS_ALLOWED_ORIGINS = ["[Link]
Q23. What is the difference between localStorage and the browser's sessionStorage
and why does it matter for security?
■ Topic: Browser Storage / Security
● Medium — should know well
■ Model Answer:
This is a summary security-focused question. Both localStorage and sessionStorage are accessible via JavaScript
(document — i.e., any script on the page). XSS (Cross-Site Scripting): if an attacker injects malicious JS into your page,
they can read EVERYTHING in localStorage and sessionStorage — including auth tokens. HttpOnly cookies: cannot be
read by JS at all — safe from XSS token theft. Best practice: store auth tokens in HttpOnly cookies (set by server), use
localStorage only for non-sensitive UI state.
■ Follow-up: How do you protect your web app from XSS?
1. Never set innerHTML with user-controlled data — use textContent or [Link](). 2. Content Security
Policy (CSP): HTTP header that whitelists script sources — blocks inline scripts and unauthorized external scripts.
Content-Security-Policy: default-src "self"; script-src "self" [Link] — even if XSS injects a script tag,
the browser refuses to execute it. 3. Use HttpOnly cookies for auth — even a full XSS exploit can't steal the token. 4.
Escape user content on the server before rendering. 5. Use a framework (React, Vue) — they escape by default.
Question Answer
typeof null? "object" — a historic JavaScript bug that cannot be fixed for backward
compatibility. Check for null with value === null.
undefined vs null? undefined: variable declared but not assigned. null: intentionally empty
value — explicitly set. typeof undefined = "undefined", typeof null = "object".
What is NaN? Not a Number — result of invalid numeric operations. NaN !== NaN (only
value not equal to itself). Use [Link]() to check.
== vs ===? === strict: checks value AND type, no coercion. == loose: coerces types
before comparing. Always use ===.
What is an IIFE? Immediately Invoked Function Expression: (function() { ... })(); — runs
immediately. Creates a new scope. Used to avoid polluting the global
scope.
What is event bubbling? Events propagate UP from the target element to the root. Parent listeners
receive events from children. Use stopPropagation() to stop.
What does preventDefault() do? Stops the default browser behaviour (form submit, link navigation, right-click
menu). Does NOT stop event bubbling.
What is the difference between null null: deliberate absence of value (you set it). undefined: JS sets it when
and undefined? variable is declared but not assigned, or property doesn't exist.
What is a Promise? Object representing an eventual async result. Three states: pending,
fulfilled, rejected. .then()/.catch()/.finally() for handling.
What is async/await? Syntactic sugar over Promises. async function always returns a Promise.
await pauses the function (not thread) until Promise resolves.
What is the DOM? Document Object Model — browser's tree representation of the HTML
document. JS reads/modifies it to make pages interactive.
querySelectorAll returns what? A static NodeList — like an array but not an array. Convert to array:
[Link](nodeList) or [...nodeList].
What is event delegation? Attach one listener to a parent, use [Link] to know which child was
clicked. Works for dynamically added elements too.
What is localStorage vs localStorage: persists across sessions, all tabs. sessionStorage: per-tab,
sessionStorage? cleared when tab closes.
What is [Link] / [Link]? stringify: JS object to JSON string. parse: JSON string to JS object.
Functions, undefined, and symbols are lost during stringify.
What is the spread operator? [...arr] copies array. {...obj} copies object. func(...args) expands array as
arguments. Always creates a shallow copy.
What is optional chaining ?.? user?.address?.city — returns undefined if any link in the chain is
null/undefined instead of throwing TypeError.
What is nullish coalescing ?? a ?? b — returns b only if a is null or undefined. Unlike ||, it doesn't trigger
for 0, "", or false.
What is the difference between map map: returns a NEW array with transformed values. forEach: returns
and forEach? undefined, used for side effects only.
What is CORS? Browser security: blocks responses from different origins. Server must send
Access-Control-Allow-Origin header. Only enforced in browsers.
Day 1 Morning 3 Section 1: Fundamentals — var/let/const, hoisting, type Type coercion table from memory.
hrs coercion, event loop. Q1–3. Draw the event loop diagram. Know
TDZ cold.
Day 1 Afternoon 3 Sections 2 & 3: ES6+ features, closures, "this", DOM + Build a product card with JS: create,
hrs events. Q4–12. style, append, add click handler. Use
delegation.
Day 1 Evening 1.5 Rapid-fire: all 20 cold. 30s each. Focus on typeof null, These catch freshers out. Know them
hrs undefined vs null, == vs ===. instantly.
Day 2 Morning 2.5 Sections 4 & 5: JS OOP (prototypes, classes), Write a class with private fields and a
hrs Promises, async/await. Q13–16. static factory method. Fetch API with
proper error handling.
Day 2 Afternoon 2 Sections 6 & 7: Storage, Forms, CORS, debounce, Implement a search with debounce.
hrs security. Q17–23. Explain CORS in your own words.
Explain XSS vs CSRF.
Day 2 Evening 1 Mock: 10 questions, 2 min each. Write code on paper. The event loop, closures, and "this"
hr Explain event loop aloud. are the top 3 most-asked JS topics.
Nail them.
Interview Day Re-read rapid-fire only. Have 2 JS code examples ready When asked to code — think aloud.
from your project. Interviewers want to see HOW you
think.
You've got this. ■ The top 3 JS topics interviewers always ask freshers: "Explain closures," "What is the event loop," and
"How does this work." Nail those three and you've already impressed. When you code live — always talk through your
thinking: "I'm using const here because this won't be reassigned", "I'm using async/await instead of .then() chaining for
readability." That commentary is what separates a 5 LPA from a 8 LPA candidate. One last tip: practise typing JS code
without autocomplete — interviewers will ask you to write it live.