Syllabus
✅ 1. JavaScript Fundamentals
Data types (primitive & reference)
Variable declarations: var, let, const
Hoisting & Temporal Dead Zone (TDZ)
Type coercion & conversion
Truthy/falsy values
Operators: ===, ==, spread/rest, optional chaining (?.)
typeof, instanceof
✅ 2. Functions & Scope
Function declarations vs expressions
Arrow functions
Closures & lexical scope
IIFE (Immediately Invoked Function Expressions)
this keyword in different contexts
Call, apply, bind
Higher-order functions
Currying and partial application
✅ 3. Asynchronous JavaScript
Callbacks and callback hell
Promises: then, catch, finally
async/await syntax and error handling
Microtasks vs macrotasks (event loop, call stack)
Fetch API and error handling
Axios (if using it)
Debouncing and throttling
✅ 4. Object-Oriented JavaScript
Object literals and prototypes
Constructor functions
class syntax and extends, super
Encapsulation via closures
Inheritance and prototype chain
Object.create, Object.assign, Object.entries, Object.keys
✅ 5. DOM Manipulation & Browser APIs
document.querySelector, getElementById, etc.
DOM traversal and updates
Event handling: bubbling, capturing, delegation
addEventListener, removing listeners
Working with forms and inputs
LocalStorage & SessionStorage
setTimeout, setInterval, requestAnimationFrame
✅ 6. ES6+ Features (must-know)
let, const
Arrow functions
Destructuring (arrays and objects)
Default parameters
Spread and rest operators
Template literals
Modules: import/export
Optional chaining ?., nullish coalescing ??
✅ 7. Array & String Methods
map, filter, reduce, forEach, some, every, find
sort, includes, indexOf, slice, splice
join, split, trim, replace, toUpperCase
Deep copy vs shallow copy techniques
✅ 8. Error Handling & Debugging
try...catch...finally
Throwing custom errors
Using console.log, breakpoints
Understanding and fixing stack traces
✅ 9. Code Quality & Practices
Writing clean, modular code
DRY, KISS, YAGNI principles
Using ESLint/Prettier
Unit testing with Jest or similar
Naming conventions
✅ 10. Common Data Structures & Algorithms in JS
Arrays, Linked Lists, Sets, Maps
Basic recursion
Sorting algorithms (bubble, merge, quick - just concepts)
Searching algorithms
String manipulation problems
Time & space complexity basics (Big O)
✅ 11. Tooling Knowledge
NPM/Yarn basics
Webpack basics (just high-level)
Babel (optional, nice to know)
Chrome DevTools (for debugging)
✅ 12. Practical Tasks You Should Know
Build a to-do app or weather app using vanilla JS
Implement debounce/throttle
Create a modal, dropdown, or tabbed interface
Form validation using JS
Fetch and render data from an API
Event delegation example
✅ 13. Soft Questions (Behavioral & Role-Fit)
How do you debug a JavaScript error?
Describe a challenge you faced in JS and how you solved it.
How do you ensure code reusability?
How do you keep up with JS updates?
Notes
✅ 1. JavaScript Fundamentals
🧠 Notes with Simple Explanation
📌 1. Data Types (Primitive & Reference)
Primitive Data Types (stored directly by value):
String, Number, Boolean, Undefined, Null, BigInt, Symbol
Reference Data Types (stored by reference):
Object, Array, Function
📌 Primitive Example:
js
CopyEdit
let a = "Hello";
let b = a;
b = "Hi";
console.log(a); // "Hello" – because it's copied by value
📌 Reference Example:
js
CopyEdit
let obj1 = { name: "Alice" };
let obj2 = obj1;
obj2.name = "Bob";
console.log(obj1.name); // "Bob" – because it's copied by reference
📌 2. Variable Declarations: var, let, const
Feature var let const
Block Block
Scope Function scope
scope scope
Redeclaratio Not Not
Allowed
n allowed allowed
Reassignme Not
Allowed Allowed
nt allowed
Yes (value:
Hoisted Yes (TDZ) Yes (TDZ)
undefined)
📌 3. Hoisting & Temporal Dead Zone (TDZ)
Hoisting: JS moves declarations to the top of the scope during
compilation.
TDZ: let and const are hoisted but not initialized. Accessing them before
declaration gives an error.
js
CopyEdit
console.log(a); // undefined
var a = 10;
console.log(b); // ReferenceError
let b = 20;
📌 4. Type Coercion & Conversion
Type coercion: JS automatically converts one type to another.
js
CopyEdit
'5' + 2 // "52" (number to string)
'5' - 2 // 3 (string to number)
true + 1 // 2
Type conversion:
js
CopyEdit
Number("5") // 5
String(5) // "5"
Boolean("") // false
Number('5t') //NaN
📌 5. Truthy / Falsy Values
Falsy Values: false, 0, "", null, undefined, NaN
Truthy: Everything else
js
CopyEdit
if ("hello") console.log("Truthy"); // This runs
if (0) console.log("Falsy"); // This doesn't run
📌 6. Operators
==: Loose equality (allows type coercion)
===: Strict equality (no type coercion)
...: Spread and Rest operator
?.: Optional chaining
js
CopyEdit
0 == false // true
0 === false // false
const obj = { a: 1 };
console.log(obj?.b?.c); // undefined (no error)
const nums = [1, 2];
const newNums = [...nums, 3]; // [1, 2, 3]
function sum(...args) {
return args.reduce((a, b) => a + b);
[] === [] → false
🔹 [1] === [1] → false
const a = [];
const b = [];
console.log(a === b); // false
const a = [1];
const b = a;
console.log(a === b); // true — same reference!
To Compare Contents (Value Comparison)
Use JSON.stringify (simple cases):
javascript
CopyEdit
JSON.stringify([1]) === JSON.stringify([1]); // true
JSON.stringify([]) === JSON.stringify([]); // true
[]===[] //false
[]==[] //false
In JavaScript, arrays (like objects) are compared by reference, not by
value.
Or use a utility function or library like Lodash:
javascript
CopyEdit
_.isEqual([1], [1]); // true
LODASH
In JavaScript, objects and arrays are compared by reference, not by value. So doing
something like [1] === [1] returns false, even though the contents look the same.
To compare arrays or objects by value, many people use JSON.stringify(), like
JSON.stringify(arr1) === JSON.stringify(arr2), but that has limitations. It doesn't
handle nested objects with undefined, functions, or different key orders.
So, I prefer using a library like Lodash, which provides _.isEqual() for deep value
comparisons. It’s clean, handles edge cases well, and is much more reliable in real-world
applications.
📌 7. typeof and instanceof
typeof: tells the data type
js
CopyEdit
typeof "hello" // "string"
typeof 42 // "number"
typeof null // "object" (quirk)
instanceof: checks object inheritance
js
CopyEdit
[] instanceof Array // true
{} instanceof Object // true
🎯 Frequently Asked Interview Questions (with Simple Answers)
❓ Q1: What is the difference between var, let, and const?
✅ Answer:
var is function-scoped, can be redeclared.
let and const are block-scoped.
let can be reassigned, const cannot.
let/const are safer due to block-scope and TDZ.
❓ Q2: What is hoisting?
✅ Answer:
Hoisting means JavaScript moves declarations (not initializations) to the
top.
Example:
js
CopyEdit
console.log(a); // undefined
var a = 5;
But with let/const, you get a ReferenceError due to TDZ.
❓ Q3: What is type coercion? Give examples.
✅ Answer:
Type coercion is JavaScript auto-converting types.
Coercion means JavaScript automatically converts a value from one type to another — type
conversion behind the scenes.
js
CopyEdit
'5' + 1 // "51"
'5' - 1 // 4
true + 1 // 2
❓ Q4: What are truthy and falsy values in JavaScript?
✅ Answer:
Falsy values: 0, "", null, undefined, false, NaN
Everything else is truthy.
❓ Q5: What is the difference between == and ===?
✅ Answer:
== checks value only, allows type conversion.
=== checks both value and type.
js
CopyEdit
'5' == 5 // true
'5' === 5 // false
❓ Q6: What is the difference between primitive and reference
types?
✅ Answer:
Primitive values are copied.
Reference types share the same memory location.
js
CopyEdit
let a = { name: "John" };
let b = a;
b.name = "Bob";
console.log(a.name); // "Bob" // 👉 "Bob" — because a and b point to the
same object
// Primitive type
let x = 10;
let y = x;
y = 20;
console.log(x); // 👉 10 — x is unchanged, because primitives are copied by
value
❓ Q7: What does typeof null return? Why?
✅ Answer:
typeof null returns "object".
This is a bug in JavaScript for historical reasons.
❓ Q8: What is optional chaining?
✅ Answer:
?. safely accesses nested properties without errors.
js
CopyEdit
let user = {};
console.log(user.address?.city); // undefined, no error
❓ Q9: What is the use of rest and spread operators?
✅ Answer:
Spread (...): expand elements
js
CopyEdit
let nums = [1, 2];
let newNums = [...nums, 3]; // [1, 2, 3]
Rest (...): collect parameters
js
CopyEdit
function sum(...args) {
return args.reduce((a, b) => a + b);
❓ Q10: What is the difference between typeof and instanceof?
✅ Answer:
typeof checks data type.
instanceof checks if an object is an instance of a class.
instanceof checks whether an object was created from a specific
class or constructor (or inherits from it).
✅ 2. Functions & Scope
(Designed for 3+ years experience, easy to explain in interviews)
🧠 Notes with Simple Examples
📌 1. Function Declarations vs Expressions
Function Function
Feature
Declaration Expression
const fn =
Syntax function name() {}
function() {}
Hoisted Yes No
Can be called before
Yes No
definition
js
CopyEdit
// Declaration
greet();
function greet() {
console.log("Hello");
// Expression
const greet2 = function () {
console.log("Hi");
};
greet2();
📌 2. Arrow Functions
Introduced in ES6
No own this, arguments, super
Shorter syntax
js
CopyEdit
const add = (a, b) => a + b;
📌 3. Closures & Lexical Scope
Closure: A function remembers its outer variables even after the outer
function has finished.
Lexical Scope : It’s is scope of variable
js
CopyEdit
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
const counter = outer();
counter(); // 1
counter(); // 2
📌 4. IIFE (Immediately Invoked Function Expression)
Used to create private scope and run function immediately.
js
CopyEdit
(function () {
console.log("I run immediately");
})();
📌 5. this Keyword in Different Contexts
Context this refers to…
In global scope window (in browser)
In object method The object itself
In arrow function Lexical (outer this)
Context this refers to…
In class The instance
In event handler The element
js
CopyEdit
const obj = {
name: "John",
greet() {
console.log(this.name); // "John"
},
};
obj.greet();
const arrow = () => console.log(this); // Arrow doesn't bind `this`
📌 6. call, apply, bind
Used to change the this context of a function.
js
CopyEdit
const person = { name: "Alice" };
function sayHi(age) {
console.log(`${this.name} is ${age}`);
sayHi.call(person, 25); // Alice is 25
sayHi.apply(person, [30]); // Alice is 30
const bound = sayHi.bind(person);
bound(35); // Alice is 35
📌 7. Higher-Order Functions (HOF)
A function that takes a function as an argument or returns a
function
js
CopyEdit
function greet(name) {
return `Hello, ${name}`;
function processName(fn, name) {
return fn(name);
console.log(processName(greet, "Sam")); // Hello, Sam
📌 8. Currying & Partial Application
Currying: Breaking a function with multiple arguments into a series of
functions with single arguments.
Currying is the process of transforming a function that takes multiple
arguments into a chain of functions, each taking a single argument.
js
CopyEdit
function sum(a) {
return function (b) {
return a + b;
};
console.log(sum(2)(3)); // 5
Partial Application: Pre-filling some arguments of a function.
js
CopyEdit
function multiply(a, b, c) {
return a * b * c;
const partial = multiply.bind(null, 2);
console.log(partial(3, 4)); // 24
🎯 Interview Questions & Answers
❓ Q1: What’s the difference between function declaration and
expression?
✅ Answer:
Declaration is hoisted, can be called before it appears.
Expression is not hoisted; defined in a variable.
❓ Q2: What are arrow functions? How are they different?
✅ Answer:
Arrow functions are shorter function syntax. They don’t have their own
this — they inherit it from their parent scope.
Also, no arguments object.
❓ Q3: What is a closure?
✅ Answer:
A closure is when a function remembers the variables from its outer
scope even after the outer function is done executing.
Example:
js
CopyEdit
function outer() {
let count = 0;
return function () {
count++;
console.log(count);
};
❓ Q4: What is an IIFE? When do you use it?
✅ Answer:
IIFE = Immediately Invoked Function Expression.
It's used to create private scope and avoid polluting the global
scope.
❓ Q5: How does this work in JavaScript?
✅ Answer:
In normal function: refers to caller object.
In arrow functions: inherits this from outer scope.
In global: refers to window (in browser).
In event handlers: refers to the HTML element.
❓ Q6: What is the use of call, apply, and bind?
✅ Answer:
They are used to manually set the this value for a function.
call: calls with arguments individually
apply: calls with arguments as array
bind: returns a new function with bound this
❓ Q7: What is a higher-order function?
✅ Answer:
A function that takes another function as input or returns another
function.
Example: map, filter, setTimeout
❓ Q8: What is currying? Give an example.
✅ Answer:
Breaking a multi-argument function into nested single-argument
functions.
js
CopyEdit
function add(a) {
return function (b) {
return a + b;
};
add(2)(3); // 5
❓ Q9: What’s the difference between currying and partial
application?
✅ Answer:
Currying transforms a function into multiple unary functions.
Partial pre-fills some arguments but still allows multiple arguments.
✅ 3. Asynchronous JavaScript
🧠 Notes with Simple Explanations
📌 1. Callbacks & Callback Hell
Callback: A function passed into another function to run later (usually
after async task).
✅ Why Use Callbacks?
To run code after something else happens, especially for:
Asynchronous operations (e.g., loading data, setTimeout)
Custom logic injections
Event handling
function greetUser(name, callback) {
console.log("Hello, " + name);
callback();
function sayBye() {
console.log("Goodbye!");
greetUser("Alice", sayBye);
// Output:
// Hello, Alice
// Goodbye!
js
CopyEdit
function getData(callback) {
setTimeout(() => {
console.log("Data received");
callback();
}, 1000);
getData(() => console.log("Processing data..."));
❗ Callback Hell: Nesting multiple callbacks leads to unreadable code:
js
CopyEdit
login(user => {
getProfile(user, profile => {
getPosts(profile, posts => {
console.log(posts);
});
});
});
📌 2. Promises: then, catch, finally
A Promise represents a future value (either success or failure).
A Promise is a JavaScript object that represents the eventual completion
(or failure) of an asynchronous operation and its resulting value.
js
CopyEdit
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("Done!"), 1000);
});
promise
.then(data => console.log(data)) // Done!
.catch(error => console.log(error))
.finally(() => console.log("Finished"));
📌 3. async/await + Error Handling
async functions allow use of await to pause code until a Promise resolves.
js
CopyEdit
async function fetchData() {
try {
let res = await fetch("https://api.example.com/data");
let data = await res.json();
console.log(data);
} catch (err) {
console.error("Error:", err);
} finally {
console.log("Done fetching.");
📌 4. Microtasks vs Macrotasks (Event Loop)
JavaScript is single-threaded but uses an event loop for async tasks.
The JavaScript Event Loop is a mechanism that continuously checks the
call stack and task queues to coordinate the execution of synchronous
and asynchronous code, ensuring that non-blocking operations (like
setTimeout, Promises, or fetch) are handled efficiently in a single-threaded
environment.
Task Type Examples Executes After...
Microtasks Promise.then, queueMicrotask After current task, before rendering
Macrotasks setTimeout, setInterval After microtasks
js
CopyEdit
console.log("Start");
setTimeout(() => console.log("Macrotask"), 0);
Promise.resolve().then(() => console.log("Microtask"));
console.log("End");
// Output: Start → End → Microtask → Macrotask
📌 5. Fetch API & Error Handling
js
CopyEdit
fetch("https://api.example.com/users")
.then(response => {
if (!response.ok) throw new Error("Network Error");
return response.json();
})
.then(data => console.log(data))
.catch(err => console.error("Fetch error:", err));
📌 6. Axios (Alternative to Fetch)
Promise-based HTTP library
Automatically converts JSON
Has better error handling
js
CopyEdit
axios.get("https://api.example.com/users")
.then(res => console.log(res.data))
.catch(err => console.error(err));
📌 7. Debouncing & Throttling
Technique Purpose
Debounci Delay execution until user stops doing
ng action
Throttling Limit the execution rate
🔁 Debounce Example (search input):
js
CopyEdit
function debounce(fn, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
const handleSearch = debounce(() => {
console.log("Search API called");
}, 500);
import React, { useState, useEffect } from 'react';
import { TextField, Button } from '@mui/material';
function SearchComponent() {
const [searchTerm, setSearchTerm] = useState('');
const [debouncedTerm, setDebouncedTerm] = useState(searchTerm);
// Update debounced term after user stops typing for 500ms
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedTerm(searchTerm);
}, 500);
return () => {
clearTimeout(handler);
};
}, [searchTerm]);
// Effect to call API whenever debouncedTerm changes
useEffect(() => {
if (debouncedTerm) {
console.log('API Call with:', debouncedTerm);
// Call your search API here
}, [debouncedTerm]);
const handleInputChange = (e) => {
setSearchTerm(e.target.value);
};
const handleSearchClick = () => {
// Optional: manual search on button click using current searchTerm
console.log('Manual API call with:', searchTerm);
// Call your search API here if needed
};
return (
<div>
<TextField
label="Search"
value={searchTerm}
onChange={handleInputChange}
variant="outlined"
size="small"
style={{ marginRight: 8 }}
/>
<Button variant="contained" onClick={handleSearchClick}>
Search
</Button>
</div>
);
export default SearchComponent;
What is Throttling?
Throttling is a technique to limit how often a function can run over
time.
You have a button that a user might click many times in a short period.
If you don’t limit the function handling those clicks, it might run too often
and cause performance issues.
Throttling makes sure the function only runs once every set amount
of time, no matter how many times the event happens.
function throttle(fn, delay) {
let lastCall = 0;
return function (...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
fn(...args);
};
}
import React, { useCallback } from 'react';
// 1️⃣ Throttle function
function throttle(fn, delay) {
let lastCall = 0;
return function (...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
fn(...args);
};
function ThrottledButton() {
// 2️⃣ Your actual click logic
const handleClick = () => {
console.log('Button clicked at:', new Date().toLocaleTimeString());
};
// 3️⃣ Wrap it with throttle using useCallback to memoize
const throttledClick = useCallback(throttle(handleClick, 2000), []);
return (
<div style={{ padding: '20px' }}>
<button onClick={throttledClick}>Click Me (throttled)</button>
</div>
);
}
export default ThrottledButton;
🎯 Frequently Asked Interview Questions (with Simple Answers)
❓ Q1: What is a callback? What is callback hell?
✅ Answer:
A callback is a function passed to another function to run later.
Callback hell is too many nested callbacks, making code hard to
read.
❓ Q2: What is a Promise?
✅ Answer:
A Promise is an object that represents the eventual result of an async
task.
It has 3 states:
pending
fulfilled
rejected
❓ Q3: How is .then/.catch different from async/await?
✅ Answer:
.then() chains promises, can get nested.
async/await is cleaner and easier to read, especially with try...catch.
❓ Q4: Explain the Event Loop and difference between microtask
and macrotask.
✅ Answer:
The event loop manages async code.
Microtasks (Promise.then) run before the next render.
Macrotasks (setTimeout) run after microtasks.
❓ Q5: How do you handle errors in async/await?
✅ Answer:
Use try...catch around await.
js
CopyEdit
try {
let res = await fetch(url);
} catch (err) {
console.log("Error:", err);
❓ Q6: What’s the difference between Fetch and Axios?
✅ Answer:
Feature Fetch Axios
Built-in Yes No (install needed)
JSON Manual
Automatic
parsing (res.json())
Error Needs res.ok Handles it
handling check automatically
❓ Q7: What is debouncing and when do you use it?
✅ Answer:
Debouncing is delaying a function until user stops doing the action — used
in search inputs, resize events, etc.
❓ Q8: What is throttling and when do you use it?
✅ Answer:
Throttling is limiting a function to run only once per interval. Useful for
scroll and mousemove events.
✅ 4. Object-Oriented JavaScript (OOP in JS)
📌 1. Object Literals and Prototypes
Object literals are the simplest way to create objects.
js
CopyEdit
const person = {
name: "Alice",
greet() {
console.log(`Hello, I'm ${this.name}`);
},
};
Every object in JS has a prototype, which allows inheritance.
js
CopyEdit
const animal = {
eats: true,
};
const rabbit = Object.create(animal);
console.log(rabbit.eats); // true
📌 2. Constructor Functions
Used to create multiple similar objects.
js
CopyEdit
function Person(name, age) {
this.name = name;
this.age = age;
}
const p1 = new Person("Bob", 30);
📌 3. Class Syntax + extends, super
Introduced in ES6, cleaner than constructor functions.
js
CopyEdit
class Animal {
constructor(name) {
this.name = name;
speak() {
console.log(`${this.name} speaks`);
class Dog extends Animal {
constructor(name, breed) {
super(name); // calls parent constructor
this.breed = breed;
bark() {
console.log(`${this.name} barks`);
📌 4. Encapsulation via Closures
Closures can protect internal variables (private data).
js
CopyEdit
function Counter() {
let count = 0; // private
return {
increment() {
count++;
console.log(count);
},
};
const counter = Counter();
counter.increment(); // 1
📌 5. Inheritance and Prototype Chain
JS uses prototype-based inheritance.
js
CopyEdit
function Animal() {}
Animal.prototype.eat = function () {
console.log("Eating...");
};
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
const d = new Dog();
d.eat(); // Eating...
📌 6. Object Utilities
js
CopyEdit
// Create object with prototype
const obj = Object.create({ role: "admin" });
// Merge objects
const user = Object.assign({}, { name: "Alice" }, { age: 25 });
// Get keys/values
console.log(Object.keys(user)); // ['name', 'age']
console.log(Object.entries(user)); // [['name', 'Alice'], ['age', 25]]
🎯 OOP Interview Questions & Answers
❓ Q1: What’s the difference between constructor function and
class?
✅ Answer:
Both create objects.
Constructor functions are old way.
class is syntactic sugar over prototype.
❓ Q2: How does inheritance work in JS?
✅ Answer:
JavaScript uses prototype-based inheritance. An object can inherit
from another via prototype.
❓ Q3: What is super() in JavaScript?
✅ Answer:
super() is used in a subclass to call the constructor of its parent class.
❓ Q4: What is Object.create used for?
✅ Answer:
It creates a new object and sets its prototype to the specified object.
❓ Q5: How can you create private variables in JavaScript?
✅ Answer:
Using closures or # (private field in class):
js
CopyEdit
class Test {
#secret = 123;
getSecret() {
return this.#secret;
✅ 5. DOM Manipulation & Browser APIs
📌 1. document.querySelector, getElementById, etc.
getElementById("id")
querySelector(".class" / "#id" / "tag")
js
CopyEdit
const el = document.querySelector("#btn");
📌 2. DOM Traversal and Updates
js
CopyEdit
el.textContent = "New Text";
el.innerHTML = "<b>Bold</b>";
el.classList.add("active");
📌 3. Event Handling: Bubbling, Capturing, Delegation
Bubbling: Event moves from target → parent
Capturing: Parent → target
Delegation: Handle event at parent level
js
CopyEdit
// Event delegation
document.getElementById("list").addEventListener("click", (e) => {
if (e.target.tagName === "LI") {
alert(e.target.textContent);
});
📌 4. addEventListener, Removing Listeners
js
CopyEdit
function handleClick() {
alert("Clicked!");
btn.addEventListener("click", handleClick);
btn.removeEventListener("click", handleClick);
📌 5. Forms and Inputs
js
CopyEdit
const form = document.querySelector("form");
form.addEventListener("submit", function (e) {
e.preventDefault();
const inputValue = document.querySelector("#name").value;
console.log(inputValue);
});
📌 6. LocalStorage & SessionStorage
js
CopyEdit
// Store
localStorage.setItem("name", "Alice");
// Read
console.log(localStorage.getItem("name"));
// Remove
localStorage.removeItem("name");
📌 7. setTimeout, setInterval, requestAnimationFrame
js
CopyEdit
setTimeout(() => console.log("Run after 1 sec"), 1000);
const id = setInterval(() => console.log("Every 2 sec"), 2000);
clearInterval(id);
// Smooth animations
function animate() {
// your animation logic
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
🎯 DOM + Browser API Interview Q&A
❓ Q1: What’s the difference between innerText, textContent,
innerHTML?
✅ Answer:
textContent: gets all text (incl. hidden)
innerText: respects styling/visibility
innerHTML: parses HTML string
❓ Q2: What is event bubbling and delegation?
✅ Answer:
Bubbling: Events propagate from child → parent
Delegation: Attach a single listener on parent to handle events for
children
❓ Q3: How to handle form submission with JavaScript?
✅ Answer:
Use addEventListener("submit", e => e.preventDefault()), then access
form fields via input.value.
❓ Q4: Difference between localStorage and sessionStorage?
✅ Answer:
sessionStorag
Feature localStorage
e
Persistenc Until manually Until tab is
e cleared closed
Scope Across tabs Per tab only
❓ Q5: What is requestAnimationFrame used for?
✅ Answer:
Used to create smooth animations. It syncs with the browser’s refresh rate
(~60 FPS).
✅ 6. ES6+ Features (Must-Know)
📌 1. let, const
let is block-scoped, can be reassigned.
const is block-scoped, cannot be reassigned (but the object/array
inside can be mutated).
js
CopyEdit
let count = 1;
const name = "John";
// name = "Jane"; ❌ Error
📌 2. Arrow Functions
Shorter syntax
Don’t have their own this, arguments, or super
js
CopyEdit
const add = (a, b) => a + b;
📌 3. Destructuring (Arrays & Objects)
js
CopyEdit
// Array
const [a, b] = [1, 2];
// Object
const user = { name: "Alice", age: 25 };
const { name, age } = user;
📌 4. Default Parameters
js
CopyEdit
function greet(name = "Guest") {
console.log("Hello, " + name);
greet(); // Hello, Guest
📌 5. Spread & Rest Operators
js
CopyEdit
// Spread (expands)
const arr = [1, 2];
const newArr = [...arr, 3]; // [1, 2, 3]
// Rest (collects)
function sum(...args) {
return args.reduce((a, b) => a + b);
📌 6. Template Literals
js
CopyEdit
const name = "Alice";
console.log(`Hello, ${name}`); // Hello, Alice
📌 7. Modules: import / export
js
CopyEdit
// file1.js
export const age = 30;
// file2.js
import { age } from './file1.js';
📌 8. Optional Chaining ?. and Nullish Coalescing ??
js
CopyEdit
// Optional chaining
const user = {};
console.log(user?.address?.city); // undefined
// Nullish coalescing
let val = null;
console.log(val ?? "Default"); // "Default"
🎯 Interview Q&A: ES6
❓ Q1: What’s the difference between let and var?
✅ Answer:
let is block-scoped, not hoisted like var
var is function-scoped and hoisted
❓ Q2: How is an arrow function different from regular function?
✅ Answer:
Arrow functions:
Don’t have their own this
Can’t be used as constructors
Shorter syntax
❓ Q3: What is destructuring?
✅ Answer:
Destructuring is extracting values from arrays or properties from objects
into variables.
❓ Q4: What’s the difference between ...rest and ...spread?
✅ Answer:
Spread expands arrays/objects
Rest gathers remaining arguments into an array
❓ Q5: What is the use of optional chaining?
✅ Answer:
It safely accesses deeply nested properties without throwing errors.
✅ 7. Array & String Methods
📌 1. map, filter, reduce, forEach, some, every, find
js
CopyEdit
const arr = [1, 2, 3, 4];
// map → transform
const squared = arr.map(x => x * x); // [1, 4, 9, 16]
// filter → condition
const even = arr.filter(x => x % 2 === 0); // [2, 4]
// reduce → accumulate
const sum = arr.reduce((acc, x) => acc + x, 0); // 10
// forEach → loop
arr.forEach(x => console.log(x));
// some → at least one true
arr.some(x => x > 3); // true
// every → all true
arr.every(x => x > 0); // true
// find → first match
arr.find(x => x > 2); // 3
📌 2. sort, includes, indexOf, slice, splice
js
CopyEdit
// sort
arr.sort((a, b) => a - b); // ascending
// includes
arr.includes(3); // true
// indexOf
arr.indexOf(2); // 1
// slice → returns part
arr.slice(1, 3); // [2, 3]
// splice → modifies original
arr.splice(2, 1); // remove at index 2
📌 3. String Methods
js
CopyEdit
let str = " Hello World ";
// join (for arrays)
["a", "b"].join("-"); // "a-b"
// split
str.split(" "); // ["", "Hello", "World", ""]
// trim
str.trim(); // "Hello World"
// replace
str.replace("World", "JS"); // " Hello JS "
// case
str.toUpperCase(); // " HELLO WORLD "
📌 4. Deep vs Shallow Copy
Shallow copy: Changes in nested objects affect the original.
js
CopyEdit
const obj1 = { a: 1, b: { c: 2 } };
const shallow = { ...obj1 };
shallow.b.c = 5;
console.log(obj1.b.c); // 5
Deep copy:
js
CopyEdit
const deep = JSON.parse(JSON.stringify(obj1)); // breaks on functions,
Date, etc.
🔹 Shallow Copy
A shallow copy duplicates only the first level of an object or array. If the original object has
nested objects, those nested objects are shared between the copy and the original (i.e. they
still refer to the same memory location).
🧪 Example:
javascript
CopyEdit
const original = {
name: 'Alice',
address: {
city: 'Wonderland'
}
};
const shallowCopy = { ...original };
shallowCopy.name = 'Bob';
shallowCopy.address.city = 'Oz';
console.log(original.name); // Alice (unchanged)
console.log(original.address.city); // Oz (changed!)
⚠️address.city was changed in both original and shallowCopy because the nested
object address was not copied deeply.
✅ Common ways to make a shallow copy:
For objects: Object.assign({}, obj) or { ...obj }
For arrays: arr.slice(), [].concat(arr), or [...arr]
🔹 Deep Copy
A deep copy duplicates everything recursively, including nested objects. The original and
the copy are completely independent.
🧪 Example:
javascript
CopyEdit
const original = {
name: 'Alice',
address: {
city: 'Wonderland'
}
};
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.address.city = 'Oz';
console.log(original.address.city); // Wonderland (unchanged)
✅ Now original.address.city remains unchanged — deep copy created a completely
separate clone.
⚠️Limitations of JSON.parse(JSON.stringify(...)):
❌ Loses functions
❌ Cannot handle undefined, Date, Map, Set, RegExp, circular references, etc.
✅ Better Deep Copy with Libraries
For more complex structures, use libraries:
Lodash:
javascript
CopyEdit
import cloneDeep from 'lodash/cloneDeep';
const deepCopy = cloneDeep(original);
✅ Summary Table
Feature Shallow Copy Deep Copy
Shared (same Cloned (different
Nested Objects
reference) reference)
Performance Faster Slower
Methods Spread, Object.assign JSON.stringify, cloneDeep
Safe for All Data
❌ ✅ (with proper method)
Types
✅ Why does shallow copy behave like that?
Example:
javascript
CopyEdit
const original = {
name: 'Alice',
address: {
city: 'Wonderland'
}
};
const shallowCopy = { ...original };
Memory-wise:
shallowCopy.name is a primitive string, so it's copied by value.
shallowCopy.address is an object, so it's copied by reference (not value).
🔍 So when you do this:
javascript
CopyEdit
shallowCopy.name = 'Bob';
This replaces the primitive value 'Alice' with 'Bob'.
✅ original.name stays 'Alice' — because primitives are copied by value.
But when you do this:
javascript
CopyEdit
shallowCopy.address.city = 'Oz';
shallowCopy.address and original.address are pointing to the same object.
❗ So modifying address.city changes it for both shallowCopy and original.
✅ In Deep Copy
javascript
CopyEdit
const deepCopy = JSON.parse(JSON.stringify(original));
Now:
deepCopy.address is a new object, not the same as original.address.
deepCopy.address.city = 'Oz' will not affect the original.
🔁 Diagram:
css
CopyEdit
Shallow Copy:
original.address ───► { city: 'Oz' } ◄─── shallowCopy.address
Deep Copy:
original.address ─► { city: 'Wonderland' }
deepCopy.address ─► { city: 'Oz' } (separate object)
✅ Summary
Effect on
Operation
Original
shallowCopy.name = 'Bob' ❌ No change
✅ Changes
shallowCopy.address.city
original
deepCopy.address.city ❌ No change
const original = {
name: 'Alice',
address: {
city: 'Wonderland'
};
const duplicate = original;
🔍 What’s Happening Here?
This is not a copy at all — neither shallow nor deep.
You're just assigning a reference:
javascript
Copy
Edit
const duplicate = original;
Now both original and duplicate point to the same object in memory.
🔁 Memory Reference:
css
Copy
Edit
original ──────┐
{ name: 'Alice', address: { city: 'Wonderland' } }
duplicate ─────┘
🔧 When you do this:
javascript
Copy
Edit
duplicate.name = 'Bob';
duplicate.address.city = 'Oz';
You’re directly modifying the same object, so:
✅ Output:
javascript
Copy
Edit
console.log(original.name); // Bob
console.log(original.address.city); // Oz
✅ Summary
Assignment type Is it a copy? Independent? Nested object cloned?
const a = b ❌ No ❌ No ❌ No
Shallow copy ✅ Yes ✅ Top-level ❌ No
Deep copy ✅ Yes ✅ Fully ✅ Yes
Conclusion:
Your code is not creating a shallow or deep copy — it’s just a reference
assignment, so changes affect both original and duplicate.
🎯 Interview Q&A: Arrays & Strings
❓ Q1: What is the difference between map and forEach?
✅ Answer:
map returns a new array
forEach doesn’t return anything, used for side effects
❓ Q2: What’s the difference between slice() and splice()?
✅ Answer:
slice() returns a shallow copy
splice() modifies the original array
✅ slice() — Non-destructive, used to copy or extract part
of an array.
📌 Returns a new array
❌ Does NOT modify the original
📌 Syntax: array.slice(start, end)
end is not included
🧪 Example:
javascript
CopyEdit
const fruits = ['apple', 'banana', 'cherry', 'date'];
const sliced = fruits.slice(1, 3);
console.log(sliced); // ['banana', 'cherry']
console.log(fruits); // ['apple', 'banana', 'cherry', 'date']
(unchanged)
✅ splice() — Destructive, used to add or remove
elements in-place.
📌 Modifies the original array
📌 Syntax: array.splice(start, deleteCount, item1, item2, ...)
Returns the removed elements
🧪 Example 1: Removing elements
javascript
CopyEdit
const fruits = ['apple', 'banana', 'cherry', 'date'];
const removed = fruits.splice(1, 2);
console.log(removed); // ['banana', 'cherry']
console.log(fruits); // ['apple', 'date'] (modified)
🧪 Example 2: Inserting elements
javascript
CopyEdit
const nums = [1, 2, 5];
nums.splice(2, 0, 3, 4); // insert at index 2, delete 0
console.log(nums); // [1, 2, 3, 4, 5]
✅ Summary Table
Feature slice() splice()
Copy/extract part of an Add/remove elements in-
Purpose
array place
Modifies
❌ No ✅ Yes
array
Feature slice() splice()
Return value New array Removed items
Use case Non-destructive copying Destructive editing
❓ Q3: When would you use reduce()?
✅ Answer:
When you need to accumulate or reduce an array to a single value (like
sum, object map, etc.)
❓ Q4: How do you check if a value exists in an array?
✅ Answer:
Use includes() or indexOf().
❓ Q5: How do you make a deep copy of an object?
✅ Answer:
Use JSON.parse(JSON.stringify(obj)), or libraries like lodash.
✅ 8. Error Handling & Debugging
📌 1. try...catch...finally
Used to catch and handle errors gracefully.
js
CopyEdit
try {
let x = y + 1; // ReferenceError
} catch (error) {
console.error("Error:", error.message);
} finally {
console.log("Always runs");
}
📌 2. Throwing Custom Errors
You can throw your own errors using throw.
js
CopyEdit
function divide(a, b) {
if (b === 0) {
throw new Error("Division by zero not allowed");
return a / b;
📌 3. console.log, Breakpoints
Use console.log() for debugging variables.
Use browser dev tools to set breakpoints and inspect variables step
by step.
📌 4. Stack Traces
A stack trace shows the path the program took before an error
happened.
js
CopyEdit
function a() {
b();
function b() {
throw new Error("Oops!");
a();
// Error: Oops!
// at b
// at a
Read from bottom-up to trace the function calls.
🎯 Error Handling Interview Q&A
❓ Q1: What is the purpose of try...catch?
✅ Answer:
It’s used to handle errors without crashing the application.
❓ Q2: What does finally do?
✅ Answer:
The finally block always runs whether there’s an error or not — useful for
cleanup tasks.
❓ Q3: How can you throw a custom error?
✅ Answer:
js
CopyEdit
throw new Error("Custom message");
❓ Q4: How do you debug JavaScript code?
✅ Answer:
Use console.log for values
Use Chrome DevTools for breakpoints
Check the call stack and errors in the console
✅ 9. Code Quality & Best Practices
📌 1. Writing Clean, Modular Code
Break logic into small functions
Avoid deeply nested code
Use meaningful names
js
CopyEdit
// ❌ Bad
function a(x) { return x + 1; }
// ✅ Good
function increment(num) { return num + 1; }
📌 2. Principles
Principle Meaning
DRY (Don't Repeat Yourself) Avoid code duplication
KISS (Keep It Simple, Stupid) Simple code is easier to maintain
YAGNI (You Ain't Gonna Don’t code features until they are
Need It) needed
📌 3. ESLint / Prettier
ESLint: Identifies code problems, style, errors.
Prettier: Auto-formats code (spacing, indentation).
Helps maintain consistent code quality.
📌 4. Unit Testing (Jest)
js
CopyEdit
// sum.js
function sum(a, b) {
return a + b;
module.exports = sum;
// sum.test.js
const sum = require("./sum");
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(3);
});
Run tests:
bash
CopyEdit
npx jest
📌 5. Naming Conventions
camelCase: variables and functions (myName)
PascalCase: classes (PersonDetails)
UPPER_SNAKE_CASE: constants (API_KEY)
Avoid 1-letter names (except counters like i, j)
🎯 Code Quality Interview Q&A
❓ Q1: What is DRY? Give an example.
✅ Answer:
DRY = Don’t Repeat Yourself. Reuse logic with functions instead of copying
code.
❓ Q2: What’s the difference between ESLint and Prettier?
✅ Answer:
ESLint catches errors & bad practices
Prettier formats code consistently
❓ Q3: What’s the benefit of writing modular code?
✅ Answer:
Easier to test, reuse, and debug
❓ Q4: Why is unit testing important?
✅ Answer:
Catches bugs early
Ensures code changes don’t break functionality
❓ Q5: What is the purpose of naming conventions?
✅ Answer:
Makes code more readable, consistent, and easier to maintain
✅ Summary
You’ve now completed:
1. JavaScript Fundamentals
2. Functions & Scope
3. Async JS
4. OOP in JS
5. DOM & Browser APIs
6. ES6+ Features
7. Array & String Methods
8. Error Handling & Debugging
9. Code Quality & Practices
✅ 10. Common Data Structures & Algorithms in JS
📌 1. Arrays, Linked Lists, Sets, Maps
✅ Arrays
Built-in ordered collection of elements.
js
CopyEdit
const arr = [1, 2, 3];
✅ Linked List (Concept)
Each node has value and next.
js
CopyEdit
function Node(val) {
this.val = val;
this.next = null;
✅ Sets
No duplicates
Fast lookup
js
CopyEdit
const s = new Set([1, 2, 2]);
s.add(3); // {1, 2, 3}
✅ Maps
Key-value pairs (keys can be any type)
js
CopyEdit
const map = new Map();
map.set("name", "Alice");
map.get("name"); // "Alice"
📌 2. Basic Recursion
A function that calls itself with a base condition.
js
CopyEdit
function factorial(n) {
if (n === 0) return 1; // base case
return n * factorial(n - 1); // recursive case
📌 3. Sorting Algorithms (Concept Only)
Algorith Time
Idea
m Complexity
Bubble Repeatedly swap
O(n²)
Sort adjacent
Merge Divide and merge
O(n log n)
Sort sorted
Quick Sort O(n log n) avg Pick pivot, partition
📌 4. Searching Algorithms
Linear Search: O(n)
Binary Search: O(log n), only on sorted arrays
js
CopyEdit
function binarySearch(arr, target) {
let left = 0, right = arr.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (arr[mid] === target) return mid;
else if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
return -1;
📌 5. String Manipulation Problems
Common:
Reverse a string
Palindrome check
Count characters
Anagram check
js
CopyEdit
function isPalindrome(str) {
return str === str.split("").reverse().join("");
📌 6. Time & Space Complexity (Big O)
Time
Operation Example
Complexity
Access in array O(1) arr[0]
linear
Search unsorted O(n)
search
binary
Search sorted O(log n)
search
Insert/remove
O(1) arr.push()
end
Insert/remove
O(n) arr.shift()
start
🎯 Interview Q&A: DSA
❓ Q1: What’s the difference between Set and Array?
✅ Answer:
Set has unique values, faster has() checks.
Array allows duplicates and indexing.
❓ Q2: Explain recursion with a real-life example.
✅ Answer:
Example: Folder inside folder — open one, then check what's inside
(recursive).
❓ Q3: When to use Map instead of Object?
✅ Answer:
When you need non-string keys
Better performance with lots of inserts/deletes
❓ Q4: Difference between Bubble Sort and Merge Sort?
✅ Answer:
Bubble: Slow, easy, O(n²)
Merge: Fast, divide & conquer, O(n log n)
❓ Q5: What’s the time complexity of accessing a value in an array?
✅ Answer:
O(1) — constant time
✅ 11. Tooling Knowledge
📌 1. NPM / Yarn Basics
NPM: Node Package Manager
Used to install/manage dependencies.
bash
CopyEdit
npm install lodash
npm uninstall lodash
npm init
Yarn: Alternative to NPM (faster, more strict)
📌 2. Webpack (High-Level)
Webpack bundles JS, CSS, etc. into a single file.
Features:
o Tree shaking (remove unused code)
o Loaders (e.g., Babel, CSS)
o Plugins
Think of Webpack as a smart packager.
📌 3. Babel (Optional, Nice to Know)
Babel transpiles modern JS (ES6+) to older JS for browser
compatibility.
bash
CopyEdit
npm install --save-dev @babel/core @babel/preset-env
📌 4. Chrome DevTools (For Debugging)
Console: Logs, errors
Sources: Breakpoints
Network: API calls, performance
Elements: DOM inspection
Application: LocalStorage, cookies, service workers
🎯 Tooling Interview Q&A
❓ Q1: What is NPM used for?
✅ Answer:
Install, remove, update JS libraries and tools.
❓ Q2: Why use Webpack?
✅ Answer:
Combines multiple files into one.
Improves performance.
Supports modular code.
❓ Q3: What does Babel do?
✅ Answer:
Converts ES6+ code to ES5 so older browsers can run it.
❓ Q4: What tools do you use for debugging?
✅ Answer:
console.log()
Chrome DevTools (breakpoints, call stack, network tab)
❓ Q5: How do you inspect LocalStorage or SessionStorage?
✅ Answer:
Open Chrome DevTools → Application tab → Storage section
✅ 12. Practical Tasks You Should Know
These are hands-on tasks that often show up in technical rounds or
take-home assessments.
📌 1. Build a To-Do App / Weather App (Vanilla JS)
🔹 Core Concepts:
DOM manipulation
Event listeners
LocalStorage (optional)
Fetch API (for weather)
js
CopyEdit
// To-Do (basic logic)
document.querySelector("#add").addEventListener("click", () => {
const task = document.querySelector("#task").value;
const list = document.createElement("li");
list.textContent = task;
document.querySelector("ul").appendChild(list);
});
📌 2. Implement Debounce / Throttle
js
CopyEdit
// Debounce: wait after user stops typing
function debounce(fn, delay) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => fn(...args), delay);
};
// Throttle: limit calls per interval
function throttle(fn, interval) {
let lastCall = 0;
return (...args) => {
if (Date.now() - lastCall >= interval) {
lastCall = Date.now();
fn(...args);
};
📌 3. Modal / Dropdown / Tabs
js
CopyEdit
// Modal
document.querySelector("#open").onclick = () => {
document.querySelector(".modal").style.display = "block";
};
document.querySelector("#close").onclick = () => {
document.querySelector(".modal").style.display = "none";
};
📌 4. Form Validation
js
CopyEdit
form.addEventListener("submit", (e) => {
const email = input.value;
if (!email.includes("@")) {
e.preventDefault();
alert("Invalid email!");
}
});
📌 5. Fetch and Render Data from API
js
CopyEdit
fetch("https://api.example.com/users")
.then(res => res.json())
.then(data => {
data.forEach(user => {
const div = document.createElement("div");
div.textContent = user.name;
document.body.appendChild(div);
});
});
📌 6. Event Delegation
js
CopyEdit
document.querySelector("#list").addEventListener("click", (e) => {
if (e.target.tagName === "LI") {
alert(`You clicked ${e.target.textContent}`);
});
✅ 13. Soft Questions (Behavioral & Role-Fit)
These are commonly asked in HR + technical behavioral rounds. Here
are ways to answer confidently:
❓ Q1: How do you debug a JavaScript error?
✅ Answer:
I start with console.log() to trace variables or logic flow. Then I use
Chrome DevTools — I set breakpoints, check the call stack, and inspect
variables at each step. I also review the error message and line number
for clues.
❓ Q2: Describe a challenge you faced in JS and how you solved it.
✅ Answer:
In one project, I faced a bug where event handlers were firing
multiple times. I found out that event listeners were added multiple
times unintentionally. I solved it by removing duplicate listeners
using .removeEventListener and checking for listener existence.
❓ Q3: How do you ensure code reusability?
✅ Answer:
I write modular functions, avoid duplication (DRY), and follow naming
conventions. I also use reusable components and keep utility functions
separate. Tools like ESLint help keep the codebase clean and consistent.
❓ Q4: How do you keep up with JavaScript updates?
✅ Answer:
I follow blogs like MDN, JavaScript Weekly, and YouTube channels (e.g.,
Fireship, Web Dev Simplified). I also read changelogs of
frameworks/libraries I use and experiment with features via
codesandbox.io or playgrounds.
❓ Q5: Why JavaScript?
✅ Answer:
JavaScript is versatile — it runs in the browser and backend (Node.js),
has a huge ecosystem, and enables fast iteration with frameworks like
React, Vue, etc. I enjoy building real-time, interactive UIs and solving real
problems with it.