Javascript
Comprehensive notes for fresher developers joining the team.
What is JavaScript?โ
JavaScript is a high-level, dynamically typed, interpreted programming language used to build interactive and dynamic web applications. It runs natively in all modern browsers and lets developers add behaviour to web pages โ things like form validation, animations, real-time content updates, and event handling.
Originally designed only for the browser, JavaScript has grown far beyond that. With environments like Node.js, JavaScript now runs on the server too, making it a true full-stack language โ the same language used on both the frontend (UI) and backend (APIs, databases).
JavaScript follows the ECMAScript standard. The major modern version is ES6 (2015) and beyond, which introduced features like let/const, arrow functions, classes, promises, and modules.
Learning Flowโ
| Phase | Topics |
|---|---|
| Phase 1 โ Core Basics | Variables, Data Types, Scope, Hoisting, Type Coercion, Template Literals |
| Phase 2 โ Functions & Logic | Operators, Conditionals, Spread/Rest, Destructuring, Functions, Arrow Functions, Callbacks, Promises, Async/Await, Closures, Currying, Memoization, Imports/Exports |
| Phase 3 โ Data Handling | Arrays, Loops, Objects, JSON, Prototypes & Classes |
| Phase 4 โ Browser Interaction | DOM Manipulation, Events |
| Phase 5 โ Web & Browser Concepts | Client-Side vs Server-Side, Browser Storage, URL, Error Handling |
| Phase 6 โ TypeScript Basics | Types, Interfaces, Generics, Typing React |
Phase 1 โ Core Basicsโ
1. Variablesโ
What is a Variable?
A variable is a named container used to store a value. JavaScript gives you three keywords to declare variables: var, let, and const.
var โ Function Scoped (Old Way)
var is the original way to declare variables. It is function-scoped โ accessible anywhere inside the function it's declared in. It can be both redeclared and reassigned, which makes it error-prone.
var x = 10;
var x = 20; // โ
redeclaring is allowed
x = 30; // โ
reassigning is allowed
function test() {
var a = 10;
console.log(a); // โ
10
}
console.log(a); // โ ReferenceError โ not accessible outside the function
let โ Block Scoped (Modern)
Introduced in ES6. let is block-scoped โ it only lives within the { } block it's declared in. It can be reassigned but not redeclared in the same scope.
let x = 10;
x = 20; // โ
reassigning allowed
let x = 30; // โ SyntaxError โ cannot redeclare
if (true) {
let a = 10;
console.log(a); // โ
10
}
console.log(a); // โ ReferenceError โ block scoped
const โ Block Scoped, Constant
Also introduced in ES6. const is block-scoped and cannot be reassigned or redeclared. It must be initialised at the time of declaration.
const x = 10;
x = 20; // โ TypeError โ cannot reassign a const
Important:
constprevents reassignment of the variable itself, but if the value is an object or array, the contents can still be modified.
const obj = { name: "John" };
obj.name = "Mike"; // โ
allowed โ modifying a property, not the variable itself
const arr = [1, 2, 3];
arr.push(4); // โ
allowed โ mutating the array contents
Comparison Table
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function | Block | Block |
| Reassignable | โ Yes | โ Yes | โ No |
| Redeclarable | โ Yes | โ No | โ No |
| Hoisted | โ
Yes (as undefined) | โ Yes (TDZ) | โ Yes (TDZ) |
| Recommended | โ Avoid | โ When value changes | โ Default choice |
Best Practice: Use
constby default. Useletonly when you know the value will change. Avoidvar.
Practice: javascript.info โ Variables ยท MDN โ let & const ยท FreeCodeCamp โ Basic JavaScript
2. Data Typesโ
JavaScript has two categories of data types:
Primitive Types (simple, single values):
| Type | Example | Description |
|---|---|---|
| String | "Hello" | Text values |
| Number | 42, 3.14 | All numbers (integer & decimal) |
| Boolean | true, false | Logical values |
| Undefined | let x; | Declared but not assigned |
| Null | let x = null; | Intentional absence of value |
| Symbol | Symbol("id") | Unique identifiers (advanced) |
| BigInt | 9007199254740991n | Very large integers (advanced) |
Reference Types (complex, stored as references):
| Type | Example |
|---|---|
| Object | { name: "John" } |
| Array | [1, 2, 3] |
| Function | function() {} |
Primitive vs Reference โ the key difference:
When you copy a primitive, you get an independent copy. When you copy an object or array, both variables point to the same memory location.
// Primitive โ independent copy
let a = 10;
let b = a;
b = 20;
console.log(a); // 10 โ unchanged
// Reference โ same memory location
let obj1 = { name: "John" };
let obj2 = obj1;
obj2.name = "Mike";
console.log(obj1.name); // "Mike" โ both affected!
// To create a true independent copy, use the spread operator:
let obj2 = { ...obj1 }; // shallow copy โ independent
Practice: javascript.info โ Data Types ยท MDN โ JavaScript Data Structures
3. Scopeโ
Scope defines where a variable is accessible in your code.
Global Scope: Declared outside any function โ accessible everywhere.
let name = "John";
function greet() {
console.log(name); // โ
accessible
}
greet();
console.log(name); // โ
accessible
Function Scope: Variables declared with var inside a function are only accessible within that function.
function test() {
var a = 10;
console.log(a); // โ
accessible
}
console.log(a); // โ ReferenceError
Block Scope: Variables declared with let or const inside { } are only accessible within that block.
if (true) {
let x = 10;
const y = 20;
console.log(x, y); // โ
accessible
}
console.log(x); // โ ReferenceError
Practice: javascript.info โ Variable Scope & Closure ยท MDN โ Scope
4. Hoistingโ
What is Hoisting?
Hoisting is JavaScript's behaviour of moving declarations to the top of their scope before code executes. This means you can reference variables and functions before they appear in the file โ but with important limitations.
var hoisting:
console.log(x); // undefined (not an error!)
var x = 10;
// JavaScript internally treats this as:
var x; // declaration hoisted
console.log(x); // undefined
x = 10;
let and const โ Temporal Dead Zone (TDZ):
let and const are hoisted but placed in a Temporal Dead Zone โ they exist but cannot be accessed before their declaration.
console.log(a); // โ ReferenceError โ TDZ
let a = 10;
Function hoisting:
Function declarations are fully hoisted โ you can call them before they appear in the code. Function expressions are not.
greet(); // โ
"Hello" โ works fine
function greet() {
console.log("Hello");
}
greet(); // โ TypeError โ greet is not a function yet
const greet = function() {
console.log("Hello");
};
Best Practice: Always declare variables and functions at the top of their scope. Never rely on hoisting.
Practice: javascript.info โ var & Hoisting ยท MDN โ Hoisting
5. Type Coercion and Conversionโ
Implicit Coercion โ JavaScript converts types automatically when needed:
"5" + 2 // "52" โ number 2 converted to string (+ triggers concat)
"5" - 2 // 3 โ string "5" converted to number (- forces numeric)
true + 1 // 2 โ true coerced to 1
false + 1 // 1 โ false coerced to 0
null + 5 // 5 โ null coerced to 0
Explicit Conversion โ you convert manually:
// To Number
Number("10") // 10
Number("10abc") // NaN
parseInt("10.9") // 10 โ integer only
parseFloat("10.9") // 10.9
// To String
String(123) // "123"
(123).toString() // "123"
// To Boolean
Boolean(1) // true
Boolean(0) // false
Boolean("") // false โ empty string is falsy
Boolean("hello") // true
Boolean([]) // true โ empty array is truthy!
Boolean({}) // true โ empty object is truthy!
Falsy values (evaluate to false in a boolean context):
0, "", null, undefined, NaN, false
Everything else is truthy.
Practice: javascript.info โ Type Conversions ยท javascript.info โ Logical Operators & Falsy Values
6. Equality Operators (== vs ===)โ
Loose Equality (==): Compares values only, with automatic type conversion.
5 == "5" // true โ "5" converted to number
true == 1 // true โ true converted to 1
null == undefined // true
Strict Equality (===): Compares both value AND type. No conversion.
5 === "5" // false โ different types
5 === 5 // true
null === undefined // false
Best Practice: Always use
===. Using==can produce unexpected results.
Practice: javascript.info โ Comparisons ยท MDN โ Equality Comparisons
7. Dynamically Typed Languageโ
In JavaScript, you do not declare the type of a variable โ it is determined automatically at runtime and can even change.
let x = 10; // x is a Number
x = "Hello"; // now x is a String
x = true; // now x is a Boolean
This is different from statically typed languages like Java or C#, where variable types are fixed at declaration.
Practice: javascript.info โ Data Types Overview ยท MDN โ typeof operator
8. Template Literalsโ
Template literals (backtick strings) allow you to embed variables and expressions directly inside strings. They also support multi-line strings.
const name = "John";
const age = 25;
// Old way
console.log("Hello, " + name + ". You are " + age + " years old.");
// Template literal
console.log(`Hello, ${name}. You are ${age} years old.`);
// Expression inside
console.log(`Next year you will be ${age + 1}.`);
// Multi-line
const message = `Line one
Line two
Line three`;
Practice: MDN โ Template Literals ยท javascript.info โ Strings
Phase 2 โ Functions & Logicโ
9. Operatorsโ
Arithmetic Operators:
let a = 10, b = 3;
console.log(a + b); // 13 โ Addition
console.log(a - b); // 7 โ Subtraction
console.log(a * b); // 30 โ Multiplication
console.log(a / b); // 3.33 โ Division
console.log(a % b); // 1 โ Modulus (remainder)
console.log(a ** b); // 1000 โ Exponentiation
console.log(++a); // 11 โ Pre-increment
console.log(a--); // 11 โ Post-decrement (returns then decrements)
Comparison Operators:
5 > 3 // true
5 < 3 // false
5 >= 5 // true
5 <= 4 // false
5 == "5" // true (loose)
5 === "5"// false (strict)
5 !== 3 // true
Logical Operators:
true && false // false โ AND (both must be true)
true || false // true โ OR (at least one must be true)
!true // false โ NOT (inverts)
// Short-circuit evaluation
let user = null;
let name = user && user.name; // null โ stops at user (falsy)
let defaultName = user || "Guest"; // "Guest" โ first truthy value
Nullish Coalescing (??): Returns the right side only if the left side is null or undefined (not for 0 or "").
let count = 0;
let result1 = count || 10; // 10 โ because 0 is falsy
let result2 = count ?? 10; // 0 โ because 0 is not null/undefined
Optional Chaining (?.): Safely accesses a nested property without throwing an error if an intermediate value is null or undefined. You will see this constantly in real codebases when working with API data or state that might not be loaded yet.
const user = null;
// Without optional chaining โ crashes if user is null
console.log(user.address.city); // โ TypeError: Cannot read properties of null
// With optional chaining โ returns undefined instead of throwing
console.log(user?.address?.city); // โ
undefined โ no crash
// Works on methods too
const name = user?.getName?.(); // only calls getName() if it exists
// Combine with ?? to provide a fallback
const city = user?.address?.city ?? "Unknown City";
console.log(city); // "Unknown City"
A common pattern you will see in the codebase โ safely accessing API response data before it loads:
const [user, setUser] = useState(null);
// Before the API call completes, user is null
// Optional chaining prevents a crash during that window
return <p>{user?.profile?.displayName ?? "Loading..."}</p>;
Ternary Operator โ shorthand for if/else:
let age = 20;
let status = age >= 18 ? "Adult" : "Minor";
console.log(status); // "Adult"
Practice: javascript.info โ Operators ยท javascript.info โ Logical Operators ยท MDN โ Expressions and Operators
10. Conditional Statementsโ
Conditional statements let your code make decisions.
if / else if / else:
let score = 75;
if (score >= 90) {
console.log("A grade");
} else if (score >= 70) {
console.log("B grade");
} else if (score >= 50) {
console.log("C grade");
} else {
console.log("Fail");
}
// Output: "B grade"
switch statement โ useful when comparing one value against many fixed options:
let day = "Monday";
switch (day) {
case "Monday":
console.log("Start of the week");
break;
case "Friday":
console.log("End of the week");
break;
case "Saturday":
case "Sunday":
console.log("Weekend!");
break;
default:
console.log("Midweek");
}
Important: Always include
breakat the end of eachcase, or execution will fall through to the next case.
Practice: javascript.info โ if/else ยท javascript.info โ switch ยท MDN โ if...else
11. Spread and Rest Operatorsโ
Both use ... but work in opposite directions.
Spread (...) โ expands an iterable into individual elements:
// Arrays
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
let copy = [...arr1]; // independent copy
// Objects
let obj1 = { a: 1, b: 2 };
let obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
let updated = { ...obj1, b: 99 }; // { a: 1, b: 99 }
// In function calls
function add(x, y, z) { return x + y + z; }
let nums = [1, 2, 3];
console.log(add(...nums)); // 6
Rest (...) โ collects multiple arguments into an array:
function sum(...numbers) {
return numbers.reduce((acc, n) => acc + n, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20, 30, 40)); // 100
// Rest must be the last parameter
function greet(greeting, ...names) {
names.forEach(name => console.log(`${greeting}, ${name}!`));
}
greet("Hello", "Alice", "Bob", "Charlie");
// Hello, Alice!
// Hello, Bob!
// Hello, Charlie!
Practice: javascript.info โ Rest & Spread ยท MDN โ Spread syntax
12. Destructuringโ
Destructuring lets you extract values from objects or arrays into individual variables โ it pairs closely with spread/rest since both are ES6 syntax for working with data structures.
Object Destructuring:
let person = { name: "John", age: 25, city: "NYC" };
const { name, age } = person;
console.log(name); // "John"
// Renaming during destructuring
const { name: fullName } = person;
console.log(fullName); // "John"
// Default values
const { country = "USA" } = person;
console.log(country); // "USA" (person has no country property)
// Nested destructuring
const { address: { city } } = { address: { city: "NYC" } };
Array Destructuring:
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [3, 4, 5]
// Swapping variables
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1
Practice: javascript.info โ Destructuring Assignment ยท MDN โ Destructuring Assignment
13. Imports and Exportsโ
JavaScript modules let you split code across files. You export from one file and import into another. This is how every React project is structured โ every component is its own file.
Named Exports โ export multiple things from one file, import them by exact name:
// mathUtils.js
export const add = (a, b) => a + b;
export const multiply = (a, b) => a * b;
export const PI = 3.14159;
// main.js
import { add, multiply, PI } from "./mathUtils";
console.log(add(2, 3)); // 5
Default Export โ one main thing per file, import it with any name you choose:
// Greeting.js
export default function Greeting() {
return "Hello!";
}
// main.js
import Greeting from "./Greeting"; // name is your choice
import SayHello from "./Greeting"; // also valid โ same file
Combining Named and Default:
// utils.js
export default function mainHelper() { ... }
export const secondaryHelper = () => { ... };
// main.js
import mainHelper, { secondaryHelper } from "./utils";
Import Aliases โ rename on import to avoid name clashes:
import { add as addNumbers } from "./mathUtils";
console.log(addNumbers(1, 2)); // 3
Re-exporting โ useful for barrel files (index.js) that collect and re-export from a folder:
// components/index.js
export { default as Button } from "./Button";
export { default as Card } from "./Card";
export { default as Modal } from "./Modal";
// Elsewhere โ one clean import instead of three
import { Button, Card, Modal } from "./components";
Named vs Default โ when to use which:
| Named Export | Default Export | |
|---|---|---|
| Syntax | export const x | export default x |
| Import syntax | import { x } | import x (any name) |
| Per file | Many allowed | Only one |
| Best for | Utilities, helpers, constants | Main component or class of a file |
Practice: javascript.info โ Import/Export ยท MDN โ export
14. Functionsโ
Function Declaration โ hoisted, can be called before it appears in code:
greet(); // โ
Works due to hoisting
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet("John")); // "Hello, John!"
Function Expression โ stored in a variable, not hoisted:
const greet = function(name) {
return `Hello, ${name}!`;
};
console.log(greet("John")); // "Hello, John!"
Practice: javascript.info โ Function Basics ยท javascript.info โ Function Expressions ยท MDN โ Functions Guide
15. Arrow Functionsโ
Arrow functions provide a shorter syntax. Introduced in ES6, they are now the standard for writing concise functions โ especially callbacks.
// Regular function
function add(a, b) {
return a + b;
}
// Arrow function (equivalent)
const add = (a, b) => {
return a + b;
};
// Implicit return โ single expression, no curly braces needed
const add = (a, b) => a + b;
// Single parameter โ no parentheses needed
const double = n => n * 2;
// No parameters
const greet = () => "Hello!";
Key Difference โ this Binding:
Arrow functions do not have their own this. They inherit this from the outer scope. This makes them ideal for callbacks but unsuitable as object methods.
function Timer() {
this.seconds = 0;
// โ Regular function โ loses 'this' inside setInterval
setInterval(function() {
this.seconds++; // 'this' is not the Timer object here
}, 1000);
// โ
Arrow function โ inherits 'this' from Timer
setInterval(() => {
this.seconds++; // correctly refers to Timer
}, 1000);
}
Practice: javascript.info โ Arrow Functions ยท MDN โ Arrow Functions
16. this Keywordโ
The this keyword refers to the current execution context โ the object that is executing the current function.
const person = {
name: "John",
greet() {
console.log("Hello, " + this.name); // 'this' refers to 'person'
}
};
person.greet(); // "Hello, John"
Arrow functions do not have their own
this. They inherit it from the surrounding context.
const obj = {
name: "John",
regularFn: function() {
console.log(this.name); // "John" โ own 'this'
},
arrowFn: () => {
console.log(this.name); // undefined โ no own 'this'
}
};
Practice: javascript.info โ Object Methods & this ยท MDN โ this
17. Callback Functionsโ
A callback is a function passed as an argument to another function, to be executed later.
function greet(name, callback) {
console.log("Hello, " + name);
callback();
}
function sayBye() {
console.log("Goodbye!");
}
greet("John", sayBye);
// Hello, John
// Goodbye!
Callback Hell โ the problem with deeply nested callbacks:
getData(function(a) {
processData(a, function(b) {
saveData(b, function(c) {
// deeply nested, hard to read and debug
});
});
});
Solution: Use Promises or Async/Await (covered below).
Practice: javascript.info โ Callbacks ยท MDN โ Callback Function
18. Higher Order Functionsโ
A Higher Order Function (HOF) is a function that either accepts another function as an argument, or returns a function.
// Accepts a function as argument
function operate(a, b, operation) {
return operation(a, b);
}
const add = (x, y) => x + y;
const multiply = (x, y) => x * y;
console.log(operate(5, 3, add)); // 8
console.log(operate(5, 3, multiply)); // 15
// Returns a function
function multiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = multiplier(2);
const triple = multiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
Built-in HOFs in JavaScript: map(), filter(), reduce(), forEach(), sort().
Practice: javascript.info โ Array Methods (map, filter, reduce) ยท FreeCodeCamp โ Functional Programming
19. Promisesโ
A Promise is an object representing the eventual completion or failure of an asynchronous operation. It is the modern replacement for deeply nested callbacks.
States of a Promise:
- Pending โ initial state, neither fulfilled nor rejected
- Fulfilled โ operation completed successfully
- Rejected โ operation failed
const fetchData = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve({ data: "User data loaded" });
} else {
reject(new Error("Failed to load data"));
}
});
fetchData
.then(result => console.log(result.data)) // "User data loaded"
.catch(err => console.error(err.message)) // if rejected
.finally(() => console.log("Done")); // always runs
Promise Chaining:
fetch("/api/user")
.then(res => res.json())
.then(user => fetch(`/api/posts?userId=${user.id}`))
.then(res => res.json())
.then(posts => console.log(posts))
.catch(err => console.error(err));
Promise.all() โ Run multiple promises in parallel:
Promise.all([
fetch("/api/users").then(r => r.json()),
fetch("/api/posts").then(r => r.json())
]).then(([users, posts]) => {
console.log(users, posts);
});
Practice: javascript.info โ Promise Basics ยท javascript.info โ Promise Chaining ยท MDN โ Using Promises
20. Async / Awaitโ
async/await is syntactic sugar over Promises โ it makes asynchronous code look and behave like synchronous code, making it much easier to read and maintain.
asyncโ marks a function as asynchronous; it always returns a Promiseawaitโ pauses execution inside an async function until the Promise resolves
async function fetchUser() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const user = await response.json();
console.log(user.name);
} catch (error) {
console.error("Error:", error.message);
} finally {
console.log("Fetch complete");
}
}
fetchUser();
Sequential vs Parallel execution:
// Sequential โ each waits for the previous
const user = await fetchUser();
const posts = await fetchPosts(user.id); // waits for user first
// Parallel โ both run simultaneously (faster)
const [user, settings] = await Promise.all([fetchUser(), fetchSettings()]);
Practice: javascript.info โ Async/Await ยท MDN โ async function ยท javascript.info โ Fetch API
21. Closuresโ
A closure is a function that remembers variables from its outer scope even after the outer function has finished executing.
function outer() {
let count = 0; // "closed over" variable
return function inner() {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3
// 'count' is preserved between calls
Practical Use โ Private Variables:
function createBankAccount(initialBalance) {
let balance = initialBalance; // private โ cannot be accessed directly
return {
deposit(amount) { balance += amount; },
withdraw(amount) { balance -= amount; },
getBalance() { return balance; }
};
}
const account = createBankAccount(1000);
account.deposit(500);
console.log(account.getBalance()); // 1500
console.log(balance); // โ ReferenceError โ balance is private
Closures are the foundation for many patterns in JavaScript: module pattern, factory functions, memoization, and more.
Practice: javascript.info โ Closure ยท MDN โ Closures
22. Curryingโ
Currying transforms a function that takes multiple arguments into a sequence of functions each taking one argument at a time.
// Normal function
function add(a, b) {
return a + b;
}
// Curried version
function curriedAdd(a) {
return function(b) {
return a + b;
};
}
console.log(curriedAdd(2)(3)); // 5
// Arrow function shorthand
const add = a => b => a + b;
console.log(add(2)(3)); // 5
Real-world use:
const multiply = factor => number => number * factor;
const double = multiply(2);
const triple = multiply(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
console.log([1, 2, 3, 4].map(double)); // [2, 4, 6, 8]
Practice: javascript.info โ Currying ยท FreeCodeCamp โ Functional Programming
23. Memoizationโ
Memoization is a performance optimisation technique that caches the results of expensive function calls so that repeated calls with the same arguments return the cached result instead of recomputing.
function memoize(fn) {
const cache = {};
return function(n) {
if (cache[n] !== undefined) {
console.log("From cache:", n);
return cache[n];
}
const result = fn(n);
cache[n] = result;
return result;
};
}
function slowSquare(n) {
return n * n; // imagine this is an expensive calculation
}
const fastSquare = memoize(slowSquare);
console.log(fastSquare(5)); // computes: 25
console.log(fastSquare(5)); // from cache: 25
console.log(fastSquare(10)); // computes: 100
Practice: javascript.info โ Closure (foundation of memoization) ยท FreeCodeCamp โ Memoization article
Phase 3 โ Data Handlingโ
24. Arraysโ
An array is an ordered collection of values stored under a single variable name. Elements are accessed by their zero-based index.
let fruits = ["Apple", "Banana", "Mango"];
console.log(fruits[0]); // "Apple"
console.log(fruits[2]); // "Mango"
console.log(fruits.length); // 3
Common Array Methods:
let arr = [1, 2, 3];
// Adding / Removing
arr.push(4); // [1, 2, 3, 4] โ add to end
arr.pop(); // [1, 2, 3] โ remove from end
arr.unshift(0); // [0, 1, 2, 3] โ add to beginning
arr.shift(); // [1, 2, 3] โ remove from beginning
// Slicing / Splicing
arr.slice(1, 3); // [2, 3] โ returns new array (non-destructive)
arr.splice(1, 1);// removes 1 element at index 1 (destructive)
// Searching
arr.indexOf(2); // 1
arr.includes(2); // true
arr.find(n => n > 1); // 2 โ first match
// Joining / Splitting
arr.join(", "); // "1, 2, 3"
"a,b,c".split(","); // ["a", "b", "c"]
// Flattening
[[1,2],[3,4]].flat(); // [1, 2, 3, 4]
Practice: javascript.info โ Arrays ยท MDN โ Array ยท FreeCodeCamp โ Basic Data Structures
25. Array Iteration Methodsโ
These are higher order functions built into arrays.
forEach() โ iterate, no return value:
let numbers = [1, 2, 3];
numbers.forEach((num, index) => {
console.log(`Index ${index}: ${num}`);
});
map() โ transform, returns a new array:
let doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6]
let users = [{ name: "Alice" }, { name: "Bob" }];
let names = users.map(u => u.name); // ["Alice", "Bob"]
filter() โ select elements matching a condition:
let evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2]
reduce() โ reduce array to a single value:
let sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum); // 6
// Find max value
let max = numbers.reduce((acc, cur) => Math.max(acc, cur));
find() and findIndex():
let users = [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }];
let found = users.find(u => u.id === 2); // { id: 2, name: "Bob" }
let index = users.findIndex(u => u.id === 2); // 1
some() and every():
let nums = [1, 2, 3, 4, 5];
nums.some(n => n > 4); // true โ at least one matches
nums.every(n => n > 0); // true โ all match
Practice: javascript.info โ Array Methods ยท MDN โ Array.prototype.map ยท FreeCodeCamp โ Functional Programming
26. Loopsโ
for Loop โ General Purpose:
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
while Loop โ Condition-Based:
let i = 0;
while (i < 3) {
console.log(i);
i++;
}
for...of โ Loop Over Arrays (values):
let colors = ["red", "green", "blue"];
for (let color of colors) {
console.log(color);
}
for...in โ Loop Over Objects (keys):
let person = { name: "John", age: 25 };
for (let key in person) {
console.log(key, person[key]);
// name John
// age 25
}
Comparison:
| Loop | Best Used For |
|---|---|
for | When you need index control or a counter |
while | When the number of iterations is unknown |
for...of | Iterating over array values |
for...in | Iterating over object keys |
forEach | Array iteration with a callback |
Practice: javascript.info โ Loops: while & for ยท MDN โ Loops and Iteration
27. Objectsโ
An object is a collection of key-value pairs used to model real-world entities. Keys are strings; values can be any type โ including functions.
let person = {
name: "John",
age: 25,
isStudent: false,
address: { city: "New York", zip: "10001" } // nested object
};
// Dot notation
console.log(person.name); // "John"
console.log(person.address.city); // "New York"
// Bracket notation (useful for dynamic keys)
let key = "age";
console.log(person[key]); // 25
// Adding / Modifying / Deleting
person.email = "john@example.com"; // add
person.age = 30; // modify
delete person.isStudent; // delete
Built-in Object Methods:
let obj = { a: 1, b: 2, c: 3 };
Object.keys(obj); // ["a", "b", "c"]
Object.values(obj); // [1, 2, 3]
Object.entries(obj); // [["a", 1], ["b", 2], ["c", 3]]
// Merge objects
let merged = { ...obj, d: 4 }; // { a:1, b:2, c:3, d:4 }
Practice: javascript.info โ Objects ยท javascript.info โ Object Methods ยท MDN โ Working with Objects
28. JSONโ
JSON (JavaScript Object Notation) is a lightweight data format used for exchanging data between a client and a server. It looks like a JavaScript object but is a string.
let person = { name: "John", age: 25, skills: ["JS", "React"] };
// Object โ JSON string (for sending to server)
let json = JSON.stringify(person);
console.log(json); // '{"name":"John","age":25,"skills":["JS","React"]}'
// JSON string โ Object (for reading from server)
let obj = JSON.parse(json);
console.log(obj.name); // "John"
JSON does not support
undefined, functions, orSymbolvalues โ these are omitted duringJSON.stringify().
Practice: javascript.info โ JSON Methods ยท MDN โ JSON.stringify
29. Prototypes and Classesโ
Prototype Chain:
Every JavaScript object has a hidden [[Prototype]] property. When you access a property that doesn't exist on an object, JavaScript automatically looks it up in the prototype chain.
function Person(name, age) {
this.name = name;
this.age = age;
}
// Adding a method to the prototype (shared across all instances)
Person.prototype.greet = function() {
console.log(`Hello, I'm ${this.name}`);
};
const p1 = new Person("Alice", 25);
const p2 = new Person("Bob", 30);
p1.greet(); // "Hello, I'm Alice"
p2.greet(); // "Hello, I'm Bob"
// Both share the same greet function in memory (efficient)
console.log(p1.greet === p2.greet); // true
Prototype chain: p1 โ Person.prototype โ Object.prototype โ null
ES6 Classes โ cleaner syntax over prototypes (under the hood, still uses prototypes):
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
const d = new Dog("Rex");
d.speak(); // "Rex barks."
Getters and Setters:
class Circle {
constructor(radius) {
this.radius = radius;
}
get area() {
return Math.PI * this.radius ** 2;
}
set diameter(d) {
this.radius = d / 2;
}
}
const c = new Circle(5);
console.log(c.area); // 78.53...
c.diameter = 20;
console.log(c.radius); // 10
Practice: javascript.info โ Prototype Inheritance ยท javascript.info โ Classes ยท MDN โ Classes
Phase 4 โ Browser Interactionโ
30. The DOMโ
The Document Object Model (DOM) is a programming interface that represents an HTML document as a tree of objects. JavaScript can use this tree to read, modify, add, or remove HTML elements dynamically โ without reloading the page.
document
โโโ html
โโโ head
โ โโโ title
โโโ body
โโโ h1#title
โโโ div.container
โโโ p
Selecting Elements:
// By ID โ returns single element
const title = document.getElementById("title");
// By CSS selector โ returns first match
const btn = document.querySelector(".btn");
// By CSS selector โ returns all matches (NodeList)
const paragraphs = document.querySelectorAll("p");
paragraphs.forEach(p => console.log(p.textContent));
Reading and Modifying Elements:
const el = document.querySelector("#title");
// Reading
console.log(el.textContent); // plain text
console.log(el.innerHTML); // HTML content
// Modifying
el.textContent = "New Title";
el.innerHTML = "<strong>Bold Title</strong>";
el.style.color = "blue";
// Classes
el.classList.add("active");
el.classList.remove("hidden");
el.classList.toggle("selected");
el.classList.contains("active"); // true/false
Creating and Inserting Elements:
const newDiv = document.createElement("div");
newDiv.textContent = "I am new!";
newDiv.className = "card";
document.body.appendChild(newDiv); // add to end of body
el.remove(); // remove an element
Attributes:
const img = document.querySelector("img");
img.getAttribute("src");
img.setAttribute("alt", "Profile picture");
img.removeAttribute("disabled");
// Data attributes โ <div data-user-id="42">
const div = document.querySelector("div");
console.log(div.dataset.userId); // "42"
Practice: javascript.info โ Document ยท javascript.info โ Modifying the Document ยท MDN โ Introduction to the DOM
31. Event Handlingโ
Events are actions triggered by the user or browser โ clicks, keyboard input, form submission, page load, etc.
const btn = document.querySelector("#myBtn");
btn.addEventListener("click", function(event) {
console.log("Button clicked!");
console.log(event.target); // the element that was clicked
});
btn.addEventListener("click", (e) => {
e.preventDefault(); // prevent default action (e.g., form submit)
e.stopPropagation(); // stop event from bubbling up to parent elements
});
Common Events:
| Event | Description |
|---|---|
click | Element clicked |
dblclick | Double click |
mouseover | Mouse enters element |
mouseout | Mouse leaves element |
keydown | Key pressed down |
keyup | Key released |
input | Input value changes |
change | Input loses focus with changed value |
submit | Form submitted |
load | Page/resource loaded |
DOMContentLoaded | HTML fully parsed |
Event Bubbling:
When an event fires on a nested element, it travels up to the root (bubbling). You can stop this with stopPropagation().
document.getElementById("parent").addEventListener("click", () => {
console.log("Parent clicked");
});
document.getElementById("child").addEventListener("click", () => {
console.log("Child clicked");
});
// Output: "Child clicked" then "Parent clicked"
Event Delegation โ add one listener to the parent instead of each child:
document.getElementById("list").addEventListener("click", (e) => {
if (e.target.tagName === "LI") {
console.log("Clicked:", e.target.textContent);
}
});
DOMContentLoaded โ fires when HTML is fully parsed. Use this to safely access DOM elements when your script runs before the HTML has loaded.
document.addEventListener("DOMContentLoaded", () => {
const btn = document.getElementById("myBtn");
btn.addEventListener("click", () => alert("Ready!"));
});
Practice: javascript.info โ Browser Events ยท javascript.info โ Event Bubbling & Delegation ยท MDN โ Introduction to Events
Quick Reference โ DOM Utilitiesโ
// Selecting
document.getElementById("id")
document.querySelector(".class")
document.querySelectorAll("tag")
// Modifying
element.textContent = "text"
element.innerHTML = "<b>html</b>"
element.setAttribute("attr", "value")
element.classList.add("class")
element.style.property = "value"
// Creating
document.createElement("div")
parent.appendChild(child)
element.remove()
// Events
element.addEventListener("event", handler)
event.preventDefault()
event.stopPropagation()
// Storage
localStorage.setItem("key", "value")
localStorage.getItem("key")
// Async
fetch(url).then(r => r.json()).then(data => ...)
async function fn() { const data = await fetch(url); }
Phase 5 โ Web & Browser Conceptsโ
32. Client-Side vs Server-Sideโ
| Feature | Client-Side | Server-Side |
|---|---|---|
| Runs on | Browser | Web Server |
| Language | JavaScript | Node.js, Python, Java, etc. |
| Purpose | UI, interactivity | Business logic, database access |
| Visible to user | Yes (source code) | No |
| Examples | Form validation, animations | API handling, authentication |
Practice: MDN โ Client-side vs Server-side ยท javascript.info โ Browser Environment
33. Browser Storageโ
localStorage โ stores data permanently in the browser (until explicitly cleared):
// Store
localStorage.setItem("username", "John");
localStorage.setItem("user", JSON.stringify({ id: 1, name: "John" }));
// Retrieve
const name = localStorage.getItem("username");
const user = JSON.parse(localStorage.getItem("user"));
// Remove
localStorage.removeItem("username");
localStorage.clear(); // removes all items
sessionStorage โ same API as localStorage, but data is cleared when the browser tab is closed:
sessionStorage.setItem("token", "abc123");
sessionStorage.getItem("token"); // "abc123"
Comparison:
| Feature | localStorage | sessionStorage | Cookies |
|---|---|---|---|
| Persistence | Until cleared | Until tab closes | Set expiry date |
| Size | ~5MB | ~5MB | ~4KB |
| Accessible in | Same origin | Same tab | Server + Client |
Practice: javascript.info โ LocalStorage & SessionStorage ยท MDN โ Window.localStorage
34. URL and Query Stringsโ
Query strings are key-value pairs appended to a URL after a ?, used to pass data between pages.
https://example.com/search?query=javascript&page=2
Reading Query Params with URLSearchParams:
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
console.log(params.get("query")); // "javascript"
console.log(params.get("page")); // "2"
console.log(params.has("query")); // true
for (const [key, value] of params) {
console.log(key, value);
}
Practice: MDN โ URLSearchParams ยท MDN โ URL API
35. Error Handlingโ
Use try/catch/finally to handle errors gracefully without crashing your program.
try {
// code that might throw an error
const data = JSON.parse("invalid json {{{");
} catch (error) {
// handle the error
console.error("Something went wrong:", error.message);
} finally {
// always runs, regardless of success or failure
console.log("Done");
}
Throwing custom errors:
function divide(a, b) {
if (b === 0) {
throw new Error("Cannot divide by zero");
}
return a / b;
}
try {
console.log(divide(10, 0));
} catch (err) {
console.error(err.message); // "Cannot divide by zero"
}
Practice: javascript.info โ Error Handling: try/catch ยท MDN โ try...catch
Phase 6 โ TypeScript Basicsโ
TypeScript is a superset of JavaScript โ it adds static type annotations on top of plain JS, then compiles back down to regular JavaScript. The browser never sees TypeScript; it only ever runs the compiled JS output.
The key difference from vanilla JavaScript: in JS you can assign any value to any variable at any time (loosely typed). TypeScript catches type mismatches at compile time, before the code ever runs.
// JavaScript โ no error until runtime
let name = "John";
name = 42; // โ
JS allows this, even though it's probably a bug
// TypeScript โ error caught immediately in your editor
let name: string = "John";
name = 42; // โ Type 'number' is not assignable to type 'string'
Practice: TypeScript โ Official Handbook ยท TypeScript Playground (run TS in the browser)
36. Basic Type Annotationsโ
TypeScript lets you declare the type of a variable after a colon. Once typed, the variable can only hold values of that type.
Primitive types:
let name: string = "John";
let age: number = 25;
let isActive: boolean = true;
Arrays:
let scores: number[] = [90, 85, 78];
let names: string[] = ["Alice", "Bob"];
any โ escape hatch (avoid where possible):
let data: any = "hello";
data = 42; // โ
no error โ any disables type checking
data = true; // โ
still no error
void โ for functions that return nothing:
function logMessage(msg: string): void {
console.log(msg);
// no return value
}
null and undefined:
let selected: string | null = null; // can be a string or null
let count: number | undefined; // can be a number or undefined
Union types โ a value that can be one of several types:
let id: string | number;
id = "abc123"; // โ
id = 42; // โ
id = true; // โ boolean not in the union
Practice: TypeScript Handbook โ Everyday Types
37. Interfaces and Type Aliasesโ
Interfaces and type aliases let you describe the shape of an object โ what properties it has and what type each one is. This is the TypeScript you will see most often when working with props, API responses, and state.
Interface:
interface User {
id: number;
name: string;
email: string;
age?: number; // optional property (the ? makes it not required)
}
// TypeScript will check any User object against this shape
const user: User = {
id: 1,
name: "John",
email: "john@example.com",
// age is optional โ fine to omit
};
Type alias โ same idea, slightly different syntax:
type Status = "active" | "inactive" | "pending"; // union of string literals
let userStatus: Status = "active"; // โ
let userStatus: Status = "deleted"; // โ not in the union
When to use which:
interface | type | |
|---|---|---|
| Best for | Object shapes | Unions, primitives, complex types |
| Extendable | Yes (extends) | Yes (& intersection) |
| Common use | Props, API data | Status values, helper types |
In React codebases you will see both โ
interfacefor component props,typefor union values and utility types. Either is fine; just be consistent.
Typing React component props โ the most common use case:
interface Props {
name: string;
age: number;
isAdmin?: boolean; // optional
onClick: () => void; // function prop
children: React.ReactNode; // anything React can render
}
function UserCard({ name, age, isAdmin = false }: Props) {
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
{isAdmin && <span>Admin</span>}
</div>
);
}
Practice: TypeScript Handbook โ Object Types
38. Typing State and Hooksโ
This is where you will see TypeScript most in React projects โ typing useState, event handlers, and refs.
Typing useState:
import { useState } from "react";
// Simple โ TypeScript infers the type from the initial value
const [count, setCount] = useState(0); // inferred: number
const [name, setName] = useState("John"); // inferred: string
// Explicit generic โ needed when initial value doesn't reveal the type
const [user, setUser] = useState<User | null>(null);
// Without <User | null>, TypeScript would infer `never` from null alone
// Array state
const [items, setItems] = useState<string[]>([]);
Typing event handlers:
// Input change event
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
console.log(e.target.value);
}
// Button click event
function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
e.preventDefault();
}
// Form submit event
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
}
Typing useRef:
const inputRef = useRef<HTMLInputElement>(null);
// inputRef.current is HTMLInputElement | null
Putting it together โ a typed form component:
interface LoginForm {
email: string;
password: string;
}
function LoginPage() {
const [form, setForm] = useState<LoginForm>({ email: "", password: "" });
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
const { name, value } = e.target;
setForm((prev) => ({ ...prev, [name]: value }));
}
return (
<form>
<input name="email" value={form.email} onChange={handleChange} />
<input name="password" value={form.password} onChange={handleChange} />
</form>
);
}
Practice: TypeScript Handbook โ Generics ยท React TypeScript Cheatsheet
39. TypeScript vs JavaScript โ Side by Sideโ
Seeing the same code in both languages shows what TypeScript adds without changing the logic.
Function:
// JavaScript
function greet(name) {
return "Hello, " + name;
}
// TypeScript
function greet(name: string): string {
return "Hello, " + name;
}
API response:
// JavaScript โ you don't know the shape until runtime
async function fetchUser() {
const res = await fetch("/api/user");
const data = await res.json(); // data is 'any' โ no safety
return data;
}
// TypeScript โ shape declared upfront, editor can help you
interface User {
id: number;
name: string;
email: string;
}
async function fetchUser(): Promise<User> {
const res = await fetch("/api/user");
const data: User = await res.json();
return data; // editor knows data.name is a string, etc.
}
Key takeaways:
- TypeScript does not change how JavaScript runs โ it only adds a safety check layer during development.
- You will see
interface,type, and generic syntax like<T>throughout React codebases โ don't panic, read the shape and treat it like a contract for what the data looks like. anydisables TypeScript's checks โ avoid it; use proper types orunknownif the type is genuinely unknown.- Start by typing props and state โ that alone catches the majority of beginner bugs.
Practice: TypeScript Handbook โ The Basics ยท React TypeScript Cheatsheet