JavaScript Complete Guide (2026): ES6+, DOM, Async Programming, APIs & Real-World Projects


JavaScript Complete Guide (2026): ES6+, DOM, Async Programming, APIs & Real-World Projects

Table of Contents

  1. What is JavaScript?
  2. Why Learn JavaScript in 2026?
  3. Features of JavaScript
  4. History of JavaScript
  5. JavaScript vs TypeScript
  6. Setting Up JavaScript
  7. Variables
  8. Data Types
  9. Operators
  10. Control Flow
  11. Loops
  12. Functions
  13. Arrays
  14. Objects
  15. ES6 Features
  16. DOM Manipulation
  17. Events
  18. JSON
  19. Local Storage
  20. Fetch API
  21. Promises
  22. Async/Await
  23. Error Handling
  24. Classes
  25. Modules
  26. Node.js Basics
  27. Best Practices
  28. Performance Optimization
  29. Security
  30. JavaScript Projects
  31. Interview Questions
  32. FAQs
  33. Conclusion 

What is JavaScript?

JavaScript is the world's most popular programming language for creating interactive websites and web applications. It powers everything from simple animations to complex applications such as Gmail, Google Maps, Netflix, and many modern AI-powered web platforms.

Unlike HTML, which structures a webpage, and CSS, which styles it, JavaScript adds behavior and interactivity. It allows developers to respond to user actions, fetch live data from servers, validate forms, create animations, and build complete front-end and back-end applications.

Today, JavaScript is no longer limited to browsers. With technologies like Node.js, developers can use JavaScript to build APIs, desktop software, mobile applications, serverless functions, and even Internet of Things (IoT) solutions.


Why Learn JavaScript in 2026?

JavaScript remains one of the most valuable programming languages for developers because of its versatility and widespread adoption.

Key reasons include:

  • Runs in every modern web browser without installation.
  • Essential for front-end frameworks like React, Vue, Angular, and Svelte.
  • Enables full-stack development through Node.js.
  • Powers progressive web apps (PWAs) and serverless applications.
  • Integrates easily with AI APIs and cloud services.
  • Backed by one of the largest open-source ecosystems.

Whether you aim to become a front-end, back-end, or full-stack developer, JavaScript is a foundational skill.


Features of JavaScript

Some of the standout features include:

  • Lightweight and interpreted.
  • Cross-platform compatibility.
  • Dynamic typing.
  • Object-oriented programming support.
  • Functional programming capabilities.
  • Event-driven architecture.
  • Asynchronous programming with Promises and Async/Await.
  • Massive ecosystem through npm.
  • Strong community support.

History of JavaScript

JavaScript was created by Brendan Eich in 1995 in just ten days while working at Netscape. Initially called Mocha, it was later renamed LiveScript and eventually JavaScript for marketing purposes.

Since then, JavaScript has evolved significantly through the ECMAScript standard, introducing modern features such as:

  • Arrow functions
  • Classes
  • Modules
  • Async/Await
  • Optional chaining
  • Nullish coalescing
  • Private class fields

Today, JavaScript is continuously updated with new features to improve developer productivity and application performance.


JavaScript vs TypeScript

FeatureJavaScriptTypeScript
TypingDynamicStatic
CompilationNot requiredRequired
Error DetectionRuntimeCompile time
Learning CurveEasierSlightly steeper
Best ForBeginners, web appsLarge enterprise projects

If you're just starting, learn JavaScript first. TypeScript builds directly on JavaScript and is much easier to pick up once you're comfortable with the language.


Setting Up JavaScript

You don't need special software to begin writing JavaScript.

Option 1: Browser Console

Open Chrome or Firefox, press F12, and navigate to the Console tab.

console.log("Hello, JavaScript!");

Option 2: HTML File

<!DOCTYPE html>
<html>
<head>
    <title>JavaScript Example</title>
</head>
<body>

<h1>Hello JavaScript</h1>

<script>
console.log("JavaScript Loaded");
</script>

</body>
</html>

Option 3: External JavaScript File

index.html

<script src="app.js"></script>

app.js

console.log("External JavaScript File");

Separating JavaScript into external files improves maintainability and is the standard practice for real-world projects.


JavaScript Variables

Variables are containers that store values.

JavaScript provides three ways to declare variables.

var

var name = "John";
console.log(name);

Avoid var in modern development because it has function scope and can lead to confusing behavior.


let

let age = 22;
console.log(age);

Use let when the variable's value will change.


const

const PI = 3.14159;
console.log(PI);

Use const by default for values that should not be reassigned.


Variable Naming Rules

Valid:

let firstName;
let userAge;
let totalMarks;

Invalid:

let 123name;
let class;
let user-name;

Choose descriptive names that clearly indicate the variable's purpose.


JavaScript Data Types

JavaScript supports both primitive and reference data types.

String

let language = "JavaScript";

Number

let marks = 95;
let price = 499.99;

Boolean

let isLoggedIn = true;

Undefined

let city;
console.log(city);

Null

let data = null;

BigInt

const large = 9007199254740991n;

Symbol

const id = Symbol("user");

Object

let student = {
    name: "Alex",
    age: 20
};

Objects allow you to group related data and are fundamental to JavaScript programming.


Type Checking

console.log(typeof "Hello");
console.log(typeof 100);
console.log(typeof true);
console.log(typeof {});
console.log(typeof []);

Remember that typeof [] returns "object", which is a well-known quirk of JavaScript.


Operators

Arithmetic Operators

let a = 20;
let b = 5;

console.log(a + b);
console.log(a - b);
console.log(a * b);
console.log(a / b);
console.log(a % b);
console.log(a ** b);

Assignment Operators

let x = 10;

x += 5;
x -= 2;
x *= 3;
x /= 2;

Comparison Operators

console.log(10 == "10");
console.log(10 === "10");
console.log(20 != 10);
console.log(20 > 15);
console.log(15 <= 20);

Prefer strict equality (===) because it avoids implicit type conversion.


Logical Operators

let age = 25;
let citizen = true;

console.log(age >= 18 && citizen);
console.log(age < 18 || citizen);
console.log(!citizen);

Control Flow

JavaScript uses conditional statements to execute different code paths based on conditions.

if Statement

let marks = 82;

if (marks >= 40) {
    console.log("Pass");
}

if...else

let temperature = 30;

if (temperature > 25) {
    console.log("Hot Weather");
} else {
    console.log("Cool Weather");
}

else if Ladder

let score = 91;

if (score >= 90) {
    console.log("Grade A");
} else if (score >= 75) {
    console.log("Grade B");
} else if (score >= 60) {
    console.log("Grade C");
} else {
    console.log("Grade D");
}

switch Statement

let day = 3;

switch (day) {
    case 1:
        console.log("Monday");
        break;
    case 2:
        console.log("Tuesday");
        break;
    case 3:
        console.log("Wednesday");
        break;
    default:
        console.log("Invalid Day");
}

Loops

Loops allow you to execute a block of code repeatedly.

for Loop

for (let i = 1; i <= 5; i++) {
    console.log(i);
}

while Loop

let count = 1;

while (count <= 5) {
    console.log(count);
    count++;
}

do...while Loop

let num = 1;

do {
    console.log(num);
    num++;
} while (num <= 5);


In this part, we'll cover the building blocks of every JavaScript program: variables, data types, operators, type conversion, template literals, and user input. Mastering these concepts will make the advanced topics later in the guide much easier.


Variables in JavaScript

Variables are named containers used to store data. Instead of repeating the same value throughout your code, you store it in a variable and reuse it whenever needed.

Think of a variable as a labeled box:

Name ─────► "John"

Age ──────► 25

Salary ───► 55000

Whenever the value changes, the variable points to the new value.


Ways to Declare Variables

Modern JavaScript provides three keywords:

  • let
  • const
  • var

1. let

Use let when the variable's value may change later.

let age = 22;

console.log(age);

age = 23;

console.log(age);

Output

22
23

Example

let score = 10;

score = score + 5;

console.log(score);

Output

15

2. const

Use const for values that should never be reassigned.

const PI = 3.14159;

console.log(PI);

Attempting to change it results in an error.

const country = "India";

country = "USA";

Output

TypeError

Good Uses of const

const company = "Google";

const TAX_RATE = 18;

const API_URL = "https://example.com/api";

Whenever possible, prefer const because it makes code easier to reason about.


3. var

var is the old way of declaring variables.

var name = "John";

Although it still works, modern JavaScript development generally favors let and const because they have more predictable scoping behavior and help prevent common bugs.


Difference Between var, let, and const

Featurevarletconst
ScopeFunctionBlockBlock
Can ReassignYesYesNo
Can RedeclareYesNoNo
HoistedYesYesYes
Modern RecommendationNoYesYes

Variable Naming Rules

Valid

let studentName;

let totalMarks;

let _count;

let $price;

let user1;

Invalid

let 1name;

let my-name;

let let;

let user name;

Variable Naming Best Practices

Good

let firstName;

let totalPrice;

let customerAge;

let isLoggedIn;

Bad

let a;

let b;

let xyz;

let temp1;

Choose descriptive names so your code is easier to understand.


JavaScript Data Types

Every value in JavaScript has a data type.

The two main categories are:

Data Types

├── Primitive

└── Non-Primitive

Primitive Data Types

JavaScript has seven primitive data types.


Number

Stores integers and floating-point numbers.

let age = 25;

let marks = 92.5;

console.log(age);

console.log(marks);

Output

25
92.5

String

Represents text.

let language = "JavaScript";

let city = 'Delhi';

console.log(language);

console.log(city);

Output

JavaScript

Delhi

Boolean

Stores true or false.

let isStudent = true;

let isLoggedIn = false;

Example

console.log(isStudent);

Output

true

Undefined

A variable that has been declared but not assigned a value.

let data;

console.log(data);

Output

undefined

Null

Represents an intentional absence of a value.

let user = null;

console.log(user);

Output

null

BigInt

Used for very large integers beyond the safe limit of the standard Number type.

let bigNumber = 1234567890123456789012345678901234567890n;

console.log(bigNumber);

Symbol

Creates unique identifiers.

let id1 = Symbol("id");

let id2 = Symbol("id");

console.log(id1 === id2);

Output

false

Non-Primitive Data Types

These are reference types.

Main examples include:

  • Objects
  • Arrays
  • Functions
  • Dates
  • Maps
  • Sets

Object

Objects store related information using key-value pairs.

let student = {

    name: "Rahul",

    age: 20,

    course: "BCA"

};

console.log(student);

Output

{
 name: "Rahul",
 age: 20,
 course: "BCA"
}

Access values

console.log(student.name);

console.log(student.age);

Array

Arrays store multiple values.

let colors = [

"Red",

"Blue",

"Green"

];

console.log(colors);

Output

["Red","Blue","Green"]

Access items

console.log(colors[0]);

console.log(colors[2]);

Output

Red

Green

Function

Functions are reusable blocks of code.

function greet(){

console.log("Welcome");

}

greet();

Output

Welcome

Functions will be explored in depth later in this guide.


Checking Data Types

JavaScript provides the typeof operator.

let age = 25;

console.log(typeof age);

Output

number

More examples

console.log(typeof "Hello");

console.log(typeof true);

console.log(typeof []);

console.log(typeof {});

Output

string

boolean

object

object

Important Note

Arrays also return "object" with typeof, which is a well-known behavior in JavaScript.

To specifically check for an array:

let items = [1, 2, 3];

console.log(Array.isArray(items));

Output

true

JavaScript Operators

Operators perform operations on values.

Main categories:

  • Arithmetic
  • Assignment
  • Comparison
  • Logical
  • Increment/Decrement
  • Ternary
  • Nullish Coalescing
  • Optional Chaining (used with objects)

Arithmetic Operators

let a = 20;

let b = 5;

console.log(a + b);

console.log(a - b);

console.log(a * b);

console.log(a / b);

console.log(a % b);

console.log(a ** b);

Output

25

15

100

4

0

3200000

Operator meanings:

OperatorDescription
+Addition
-Subtraction
*Multiplication
/Division
%Modulus (remainder)
**Exponentiation

Assignment Operators

let x = 10;

x += 5;

console.log(x);

Output

15

Other assignment operators include:

x -= 2;

x *= 3;

x /= 2;

x %= 2;

Comparison Operators

Comparison operators return a boolean value (true or false).

console.log(10 > 5);

console.log(10 < 5);

console.log(10 >= 10);

console.log(10 <= 8);

console.log(10 == "10");

console.log(10 === "10");

console.log(10 != 20);

console.log(10 !== "10");

Output

true

false

true

false

true

false

true

true

== vs ===

console.log(5 == "5");

Output

true

Because == performs type coercion.

console.log(5 === "5");

Output

false

=== checks both value and data type, making it the preferred choice in modern JavaScript.


Logical Operators

Logical operators are commonly used in conditions.

let age = 20;

let hasLicense = true;

console.log(age >= 18 && hasLicense);

Output

true

Examples

console.log(true || false);

console.log(!true);

Output

true

false

Increment and Decrement Operators

let count = 5;

count++;

console.log(count);

Output

6
count--;

console.log(count);

Output

5

Type Conversion

JavaScript can convert values between different data types.


String to Number

let marks = "95";

console.log(Number(marks));

Output

95

Number to String

let age = 21;

console.log(String(age));

Output

"21"

Boolean Conversion

console.log(Boolean(1));

console.log(Boolean(0));

console.log(Boolean(""));

Output

true

false

false

Common truthy values include non-empty strings, non-zero numbers, arrays, and objects. Common falsy values include false, 0, "", null, undefined, and NaN.


Template Literals

Template literals make string creation cleaner and more readable.

Old style

let name = "Alice";

console.log("Hello " + name);

Modern style

let name = "Alice";

console.log(`Hello ${name}`);

Output

Hello Alice

You can also embed expressions.

let a = 10;

let b = 20;

console.log(`Sum = ${a + b}`);

Output

Sum = 30

Template literals also support multi-line strings.

let message = `Welcome
to the
JavaScript Complete Guide`;

console.log(message);

Getting User Input

In the browser, you can use prompt() to receive input from the user.

let name = prompt("Enter your name:");

console.log(name);

You can combine it with template literals.

let city = prompt("Enter your city:");

console.log(`You live in ${city}.`);

Note: prompt() is available in browsers but not in Node.js by default.


Common Beginner Mistakes

  • Using var instead of let or const in new code.
  • Using == when === is the safer choice.
  • Forgetting that prompt() returns a string.
  • Reassigning a const variable.
  • Choosing vague variable names like x or temp for important data.
  • Confusing null and undefined.

Practice Exercises

  1. Create variables for your name, age, and favorite programming language, then print them.
  2. Calculate the area of a rectangle using variables for length and width.
  3. Convert the string "150" into a number and add 50.
  4. Use template literals to display your profile in one sentence.
  5. Compare two numbers using all comparison operators.
  6. Create an object representing a book with title, author, and price.
  7. Create an array of five programming languages and print the third one.
  8. Use typeof on every primitive data type.
  9. Write a program that increments a counter five times.
  10. Ask the user for their name using prompt() and greet them.


Now that you understand variables, data types, and operators, it's time to make your programs intelligent. In this part, you'll learn how JavaScript makes decisions, repeats tasks efficiently, and controls program execution using conditions and loops.


Control Flow in JavaScript

Control flow determines the order in which JavaScript executes statements.

Without control flow, every line of code would run from top to bottom. In real applications, we often need to:

  • Make decisions
  • Repeat tasks
  • Skip certain operations
  • Stop execution when a condition is met

Control flow provides these capabilities.

Start
   │
   ▼
Condition?
 ┌───────┐
 │ True  │────► Execute Block A
 └───────┘
      │
      ▼
 ┌───────┐
 │ False │────► Execute Block B
 └───────┘
      │
      ▼
 Continue Program

The if Statement

The if statement executes a block of code only if a condition evaluates to true.

Syntax

if (condition) {
    // code
}

Example

let age = 20;

if (age >= 18) {
    console.log("You are eligible to vote.");
}

Output

You are eligible to vote.

Another Example

let temperature = 35;

if (temperature > 30) {
    console.log("It's a hot day.");
}

Output

It's a hot day.

if...else Statement

Use if...else when there are two possible outcomes.

let marks = 40;

if (marks >= 35) {
    console.log("Pass");
} else {
    console.log("Fail");
}

Output

Pass

Example: Login System

let password = "admin123";

if (password === "admin123") {
    console.log("Login Successful");
} else {
    console.log("Invalid Password");
}

Output

Login Successful

else if Statement

Use else if when checking multiple conditions.

let marks = 88;

if (marks >= 90) {
    console.log("Grade A+");
}
else if (marks >= 80) {
    console.log("Grade A");
}
else if (marks >= 70) {
    console.log("Grade B");
}
else if (marks >= 60) {
    console.log("Grade C");
}
else {
    console.log("Fail");
}

Output

Grade A

Real Example: Income Tax Category

let income = 850000;

if (income < 300000) {
    console.log("No Tax");
}
else if (income < 700000) {
    console.log("5% Tax");
}
else if (income < 1200000) {
    console.log("10% Tax");
}
else {
    console.log("20% Tax");
}

Nested if Statements

An if statement can contain another if statement.

let age = 24;
let hasLicense = true;

if (age >= 18) {

    if (hasLicense) {
        console.log("You can drive.");
    }

}

Output

You can drive.

Truthy and Falsy Values

JavaScript doesn't always require a boolean in conditions.

Example

let username = "Alice";

if (username) {
    console.log("Welcome!");
}

Output

Welcome!

Falsy values include:

  • false
  • 0
  • ""
  • null
  • undefined
  • NaN

Everything else is generally considered truthy.


switch Statement

switch is useful when comparing one value against many fixed options.

Syntax

switch(expression){

case value1:
// code
break;

case value2:
// code
break;

default:
// code

}

Example

let day = 3;

switch(day){

case 1:
console.log("Monday");
break;

case 2:
console.log("Tuesday");
break;

case 3:
console.log("Wednesday");
break;

default:
console.log("Invalid Day");

}

Output

Wednesday

Calculator Example

let operation = "+";

switch(operation){

case "+":
console.log(15 + 10);
break;

case "-":
console.log(15 - 10);
break;

case "*":
console.log(15 * 10);
break;

case "/":
console.log(15 / 10);
break;

default:
console.log("Invalid Operator");

}

Ternary Operator

A shorter alternative to if...else.

Syntax

condition ? value1 : value2

Example

let age = 20;

let result = age >= 18 ? "Adult" : "Minor";

console.log(result);

Output

Adult

Another Example

let number = 7;

console.log(number % 2 === 0 ? "Even" : "Odd");

Output

Odd

for Loop

The for loop repeats code a fixed number of times.

Syntax

for(initialization; condition; update){

// code

}

Example

for(let i = 1; i <= 5; i++){

console.log(i);

}

Output

1
2
3
4
5

Print Squares

for(let i = 1; i <= 10; i++){

console.log(i * i);

}

Output

1
4
9
16
25
36
49
64
81
100

Sum of Numbers

let sum = 0;

for(let i = 1; i <= 100; i++){

sum += i;

}

console.log(sum);

Output

5050

while Loop

Runs while a condition is true.

let i = 1;

while(i <= 5){

console.log(i);

i++;

}

Output

1
2
3
4
5

Countdown Example

let countdown = 10;

while(countdown > 0){

console.log(countdown);

countdown--;

}

console.log("Lift Off!");

do...while Loop

Runs at least once.

let number = 1;

do{

console.log(number);

number++;

}
while(number <= 5);

Output

1
2
3
4
5

Difference Between while and do...while

whiledo...while
Checks condition firstExecutes once before checking
May never executeExecutes at least once

Infinite Loops

Incorrect

while(true){

console.log("Hello");

}

This loop never stops and should generally be avoided unless you intentionally provide a way to exit it.


break Statement

Stops a loop immediately.

for(let i = 1; i <= 10; i++){

if(i === 6){

break;

}

console.log(i);

}

Output

1
2
3
4
5

continue Statement

Skips the current iteration.

for(let i = 1; i <= 5; i++){

if(i === 3){

continue;

}

console.log(i);

}

Output

1
2
4
5

Nested Loops

A loop inside another loop.

for(let i = 1; i <= 3; i++){

for(let j = 1; j <= 3; j++){

console.log(i, j);

}

}

Output

1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3

Pattern Printing Example

for(let i = 1; i <= 5; i++){

let stars = "";

for(let j = 1; j <= i; j++){

stars += "*";

}

console.log(stars);

}

Output

*
**
***
****
*****

Looping Through Arrays

let languages = [

"JavaScript",

"Python",

"Java",

"C++"

];

for(let i = 0; i < languages.length; i++){

console.log(languages[i]);

}

Output

JavaScript
Python
Java
C++

for...of Loop

Best for iterating over arrays and other iterable objects.

const colors = ["Red", "Green", "Blue"];

for (const color of colors) {
    console.log(color);
}

Output

Red
Green
Blue

for...in Loop

Used for iterating over object properties.

const student = {
    name: "Rahul",
    age: 20,
    course: "BCA"
};

for (const key in student) {
    console.log(key, student[key]);
}

Output

name Rahul
age 20
course BCA

Tip: Prefer for...of for arrays and for...in for objects.


Optional Chaining (?.)

Optional chaining prevents runtime errors when accessing nested properties that may not exist.

const user = {
    profile: {
        name: "Alice"
    }
};

console.log(user.profile?.name);
console.log(user.address?.city);

Output

Alice
undefined

Without optional chaining, accessing user.address.city would throw an error.


Nullish Coalescing (??)

The nullish coalescing operator provides a default value only when the left-hand side is null or undefined.

let username = null;

console.log(username ?? "Guest");

Output

Guest

Compare it with the logical OR operator:

console.log("" || "Default");
console.log("" ?? "Default");

Output

Default

""

This makes ?? a better choice when empty strings or 0 are valid values.


Practical Exercise: Multiplication Table

let number = 7;

for (let i = 1; i <= 10; i++) {
    console.log(`${number} x ${i} = ${number * i}`);
}

Output

7 x 1 = 7
...
7 x 10 = 70

Practice Exercises

  1. Check whether a number is positive, negative, or zero.
  2. Find the largest of three numbers using if...else.
  3. Print all even numbers from 1 to 100.
  4. Calculate the factorial of a number using a loop.
  5. Reverse the digits of an integer.
  6. Count the number of vowels in a string.
  7. Print the Fibonacci sequence up to n terms.
  8. Create a simple menu using switch.
  9. Generate different star patterns using nested loops.
  10. Iterate through an object using for...in and an array using for...of.

Functions are the foundation of modern JavaScript. Every framework, library, API, and application relies heavily on functions. In this part, you'll learn how to write reusable code, understand scope, use modern ES6+ syntax, and explore concepts like closures and higher-order functions that are frequently asked in interviews.


What is a Function?

A function is a reusable block of code designed to perform a specific task. Instead of writing the same logic multiple times, you write it once and call it whenever needed.

Why Use Functions?

Functions help you:

  • Reuse code
  • Improve readability
  • Reduce duplication
  • Organize large applications
  • Simplify debugging and maintenance

Without functions, even small applications become difficult to manage.


Function Declaration

A function declaration is the most common way to define a function.

Syntax

function functionName(parameters) {
    // code
}

Example

function greet() {
    console.log("Welcome to JavaScript!");
}

greet();

Output

Welcome to JavaScript!

Functions with Parameters

Parameters allow you to pass data into a function.

function greet(name) {
    console.log("Hello " + name);
}

greet("Alice");
greet("Rahul");
greet("John");

Output

Hello Alice
Hello Rahul
Hello John

Multiple Parameters

function add(a, b) {
    console.log(a + b);
}

add(10, 20);
add(5, 8);

Output

30
13

Returning Values

Functions can return data using the return keyword.

function multiply(a, b) {
    return a * b;
}

let result = multiply(8, 5);

console.log(result);

Output

40

Why Return Instead of console.log()?

Consider the following:

function square(number) {
    return number * number;
}

let answer = square(6);

console.log(answer + 10);

Output

46

Returning values allows other parts of your program to reuse the result.


Function Expressions

Functions can also be assigned to variables.

const greet = function() {

    console.log("Hello!");

};

greet();

Output

Hello!

Anonymous Functions

Functions without names are called anonymous functions.

const message = function() {

console.log("Anonymous Function");

};

message();

Arrow Functions (ES6)

Arrow functions provide a shorter syntax.

Traditional

function add(a, b){

return a + b;

}

Arrow

const add = (a, b) => {

return a + b;

};

Single Parameter

const square = number => {

return number * number;

};

console.log(square(5));

Output

25

One-Line Arrow Function

const cube = number => number * number * number;

console.log(cube(3));

Output

27

Default Parameters

Default values are used when an argument is not provided.

function greet(name = "Guest"){

console.log("Welcome " + name);

}

greet();

greet("Alice");

Output

Welcome Guest

Welcome Alice

Rest Parameters

Rest parameters collect multiple arguments into an array.

function total(...numbers){

let sum = 0;

for(const number of numbers){

sum += number;

}

return sum;

}

console.log(total(5,10,15,20));

Output

50

Spread Operator

The spread operator expands arrays or objects.

const numbers = [10,20,30];

console.log(...numbers);

Output

10 20 30

Copy arrays

const original = [1,2,3];

const copy = [...original];

console.log(copy);

Output

[1,2,3]

Merge arrays

const frontend = [

"HTML",

"CSS"

];

const backend = [

"Node.js",

"MongoDB"

];

const fullstack = [

...frontend,

"JavaScript",

...backend

];

console.log(fullstack);

Output

["HTML","CSS","JavaScript","Node.js","MongoDB"]

Function Scope

Variables exist only within certain parts of your program.

JavaScript has:

  • Global Scope
  • Function Scope
  • Block Scope

Global Scope

let language = "JavaScript";

function show(){

console.log(language);

}

show();

Output

JavaScript

Local Scope

function test(){

let message = "Hello";

console.log(message);

}

test();

Trying to access message outside the function results in an error.


Block Scope

Variables declared using let and const exist only inside the block where they are defined.

if(true){

let score = 100;

console.log(score);

}

Outside the block:

console.log(score);

Output

ReferenceError

Hoisting

JavaScript moves declarations to the top of their scope during compilation.

Example

greet();

function greet(){

console.log("Hello");

}

Output

Hello

However, function expressions and arrow functions are not initialized in the same way.

sayHello();

const sayHello = () => {

console.log("Hi");

};

Output

ReferenceError

Callback Functions

A callback is a function passed as an argument to another function.

function welcome(name){

console.log("Welcome " + name);

}

function process(callback){

callback("Alice");

}

process(welcome);

Output

Welcome Alice

Callbacks are widely used in asynchronous programming, event handling, and APIs.


Higher-Order Functions

A higher-order function either:

  • Accepts another function as an argument, or
  • Returns a function.

Example

function calculator(operation){

return operation(10,5);

}

function add(a,b){

return a+b;

}

console.log(calculator(add));

Output

15

Closures

A closure occurs when an inner function remembers variables from its outer function even after the outer function has finished executing.

function counter(){

let count = 0;

return function(){

count++;

console.log(count);

};

}

const increment = counter();

increment();

increment();

increment();

Output

1
2
3

Closures are commonly used for:

  • Data privacy
  • State management
  • Function factories
  • Event handlers

Immediately Invoked Function Expression (IIFE)

An IIFE runs immediately after it is defined.

(function(){

console.log("Executed Immediately");

})();

Output

Executed Immediately

IIFEs were commonly used before ES6 modules to avoid polluting the global scope.


Recursive Functions

A recursive function calls itself.

Example: Factorial

function factorial(n){

if(n===0){

return 1;

}

return n * factorial(n-1);

}

console.log(factorial(5));

Output

120

Function Overloading?

JavaScript does not support traditional function overloading.

Example

function test(){

console.log("One");

}

function test(name){

console.log(name);

}

test("Alice");

Output

Alice

The second declaration replaces the first one.


Pure Functions

A pure function:

  • Produces the same output for the same input.
  • Does not modify external state.
  • Has no side effects.
function add(a,b){

return a+b;

}

Pure functions are easier to test and maintain.


Impure Function

let total = 0;

function add(value){

total += value;

}

This function modifies external state, making it impure.


First-Class Functions

JavaScript treats functions as first-class citizens.

Functions can be:

  • Stored in variables
  • Passed as arguments
  • Returned from other functions
  • Stored inside arrays or objects

Example

const greet = () => "Hello";

const functions = [

greet

];

console.log(functions[0]());

Output

Hello

Practical Example: Simple Calculator

function calculate(a, b, operation){

switch(operation){

case "+":
return a+b;

case "-":
return a-b;

case "*":
return a*b;

case "/":
return a/b;

default:
return "Invalid Operation";

}

}

console.log(calculate(15,5,"+"));

console.log(calculate(15,5,"*"));

Output

20

75

Practical Example: Temperature Converter

const celsiusToFahrenheit = celsius => (celsius * 9/5) + 32;

console.log(celsiusToFahrenheit(30));

Output

86

Common Mistakes

❌ Forgetting to return a value.

function add(a,b){

a+b;

}

Correct

function add(a,b){

return a+b;

}

❌ Calling a function without parentheses.

Incorrect

greet;

Correct

greet();

❌ Using var instead of const or let in modern code.


❌ Confusing function declarations with arrow functions when relying on hoisting.


Interview Questions

What is the difference between parameters and arguments?

  • Parameters are variables listed in the function definition.
  • Arguments are the actual values passed when calling the function.

What is a callback function?

A function passed as an argument to another function and executed later.


What is a closure?

A closure is an inner function that retains access to variables from its outer lexical scope even after the outer function has returned.


What is a higher-order function?

A function that accepts another function as an argument or returns a function.


Why use arrow functions?

  • Shorter syntax
  • Lexical this binding
  • Cleaner callback code
  • Commonly used in React and modern JavaScript

Practice Exercises

  1. Write a function to check whether a number is prime.
  2. Create a function that reverses a string.
  3. Find the largest element in an array using a function.
  4. Create an arrow function that calculates the average of three numbers.
  5. Write a recursive function to generate Fibonacci numbers.
  6. Build a calculator using functions.
  7. Create a function that removes duplicate elements from an array.
  8. Use rest parameters to find the maximum number.
  9. Write a function that accepts another function as a callback.
  10. Create a closure that tracks how many times a button has been clicked.


Arrays and objects are the backbone of JavaScript applications. Whether you're building a React application, processing API responses, or managing user data, you'll work with arrays and objects every day. In this section, you'll master modern array methods, object manipulation, ES6 collections, and practical examples used in production applications.


Arrays in JavaScript

An array is an ordered collection of values stored in a single variable.

Instead of creating multiple variables:

let student1 = "Alice";
let student2 = "Bob";
let student3 = "Charlie";

You can use one array:

const students = ["Alice", "Bob", "Charlie"];

Creating Arrays

Using Array Literals (Recommended)

const fruits = ["Apple", "Banana", "Orange"];

console.log(fruits);

Output

["Apple", "Banana", "Orange"]

Using the Array Constructor

const numbers = new Array(10, 20, 30);

console.log(numbers);

Output

[10, 20, 30]

Array literals are preferred because they are simpler and more readable.


Accessing Array Elements

Array indexing starts from 0.

const colors = ["Red", "Green", "Blue"];
console.log(colors[0]);

console.log(colors[1]);

console.log(colors[2]);

Output

Red

Green

Blue

Modifying Arrays

const languages = [

"Java",

"Python",

"C++"

];

languages[1] = "JavaScript";

console.log(languages);

Output

["Java","JavaScript","C++"]

Array Length

const numbers = [5,10,15,20];

console.log(numbers.length);

Output

4

Adding Elements

push()

Adds an element to the end.

const cities = [

"Delhi",

"Mumbai"

];

cities.push("Pune");

console.log(cities);

Output

["Delhi","Mumbai","Pune"]

unshift()

Adds to the beginning.

cities.unshift("Nagpur");

console.log(cities);

Output

["Nagpur","Delhi","Mumbai","Pune"]

Removing Elements

pop()

Removes the last element.

const numbers = [1,2,3,4];

numbers.pop();

console.log(numbers);

Output

[1,2,3]

shift()

Removes the first element.

numbers.shift();

console.log(numbers);

Output

[2,3]

Finding Elements

includes()

const fruits = [

"Apple",

"Banana",

"Mango"

];

console.log(fruits.includes("Banana"));

Output

true

indexOf()

console.log(fruits.indexOf("Mango"));

Output

2

If the element is not found:

-1

Joining Arrays

const languages = [

"HTML",

"CSS",

"JavaScript"

];

console.log(languages.join(" - "));

Output

HTML - CSS - JavaScript

slice()

Returns a portion of an array without modifying the original.

const numbers = [10,20,30,40,50];

console.log(numbers.slice(1,4));

Output

[20,30,40]

Original array remains unchanged.


splice()

Adds or removes elements by modifying the original array.

const numbers = [10,20,30,40];

numbers.splice(2,1);

console.log(numbers);

Output

[10,20,40]

Looping Through Arrays

Classic for loop

const colors = [

"Red",

"Green",

"Blue"

];

for(let i=0;i<colors.length;i++){

console.log(colors[i]);

}

for...of

for(const color of colors){

console.log(color);

}

This is the preferred approach for arrays.


forEach()

Executes a callback for every element.

const numbers = [10,20,30];

numbers.forEach(function(number){

console.log(number);

});

Output

10

20

30

Arrow function version

numbers.forEach(number => console.log(number));

map()

Creates a new array by transforming each element.

const prices = [100,200,300];

const discounted = prices.map(price => price * 0.9);

console.log(discounted);

Output

[90,180,270]

Original array remains unchanged.


Real Example

const users = [

{name:"Alice"},

{name:"Bob"},

{name:"John"}

];

const names = users.map(user => user.name);

console.log(names);

Output

["Alice","Bob","John"]

filter()

Returns only elements matching a condition.

const ages = [15,18,25,12,40];

const adults = ages.filter(age => age >= 18);

console.log(adults);

Output

[18,25,40]

reduce()

Reduces an array to a single value.

const numbers = [10,20,30];

const total = numbers.reduce((sum,number)=>{

return sum + number;

},0);

console.log(total);

Output

60

Real Example: Shopping Cart

const cart = [

{price:500},

{price:300},

{price:200}

];

const totalPrice = cart.reduce((total,item)=>{

return total + item.price;

},0);

console.log(totalPrice);

Output

1000

find()

Returns the first matching element.

const users = [

{name:"Alice"},

{name:"Bob"},

{name:"Charlie"}

];

const user = users.find(user=>user.name==="Bob");

console.log(user);

Output

{name:"Bob"}

findIndex()

const numbers = [15,30,45,60];

console.log(numbers.findIndex(number=>number===45));

Output

2

some()

Returns true if at least one element satisfies the condition.

const marks = [45,60,80];

console.log(marks.some(mark=>mark>=75));

Output

true

every()

Returns true only if every element satisfies the condition.

console.log(marks.every(mark=>mark>=35));

Output

true

sort()

Default sorting.

const names = [

"John",

"Alice",

"David"

];

names.sort();

console.log(names);

Output

["Alice","David","John"]

Sorting Numbers

Incorrect

const numbers = [10,2,50];

numbers.sort();

console.log(numbers);

Output

[10,2,50]

Correct

numbers.sort((a,b)=>a-b);

console.log(numbers);

Output

[2,10,50]

Descending

numbers.sort((a,b)=>b-a);

reverse()

const numbers = [1,2,3];

numbers.reverse();

console.log(numbers);

Output

[3,2,1]

flat()

Flattens nested arrays.

const values = [

1,

2,

[3,4],

[5,[6]]

];

console.log(values.flat());

console.log(values.flat(2));

Output

[1,2,3,4,5,[6]]

[1,2,3,4,5,6]

Objects in JavaScript

Objects store data using key-value pairs.

const student = {

name:"Rahul",

age:20,

course:"BCA"

};

Accessing Properties

Dot notation

console.log(student.name);

Bracket notation

console.log(student["course"]);

Updating Properties

student.age = 21;

console.log(student);

Adding Properties

student.city = "Nagpur";

console.log(student);

Deleting Properties

delete student.course;

Object Methods

const person = {

name:"Alice",

greet(){

console.log("Hello " + this.name);

}

};

person.greet();

Output

Hello Alice

Object.keys()

console.log(Object.keys(student));

Output

["name","age","city"]

Object.values()

console.log(Object.values(student));

Output

["Rahul",21,"Nagpur"]

Object.entries()

console.log(Object.entries(student));

Output

[
["name","Rahul"],
["age",21],
["city","Nagpur"]
]

Destructuring Arrays

const colors = [

"Red",

"Green",

"Blue"

];

const [first,second] = colors;

console.log(first);

console.log(second);

Output

Red

Green

Object Destructuring

const user = {

name:"Alice",

age:25

};

const {name,age} = user;

console.log(name);

console.log(age);

Renaming Variables During Destructuring

const {name:username} = user;

console.log(username);

Spread Operator with Objects

const student = {

name:"Rahul",

age:20

};

const updatedStudent = {

...student,

city:"Nagpur"

};

console.log(updatedStudent);

ES6 Map

A Map stores key-value pairs and allows keys of any type.

const userRoles = new Map();

userRoles.set("Alice", "Admin");
userRoles.set("Bob", "Editor");
userRoles.set(101, "Guest");

console.log(userRoles.get("Alice"));
console.log(userRoles.has("Bob"));
console.log(userRoles.size);

Output

Admin
true
3

Iterating over a Map:

for (const [user, role] of userRoles) {
    console.log(user, role);
}

ES6 Set

A Set stores only unique values.

const uniqueNumbers = new Set([1, 2, 2, 3, 4, 4]);

console.log(uniqueNumbers);

Output

Set(4) {1, 2, 3, 4}

Adding and removing values:

uniqueNumbers.add(5);
uniqueNumbers.delete(2);

console.log(uniqueNumbers.has(3));

Removing Duplicate Values

One of the most common real-world uses of Set:

const numbers = [1, 2, 2, 3, 4, 4, 5];

const unique = [...new Set(numbers)];

console.log(unique);

Output

[1, 2, 3, 4, 5]

Immutable Array Methods (Modern JavaScript)

Newer JavaScript versions introduced non-mutating alternatives that return new arrays instead of changing the original.

const numbers = [3, 1, 2];

const sorted = numbers.toSorted();

console.log(numbers);
console.log(sorted);

Output

[3, 1, 2]
[1, 2, 3]

Other useful immutable methods include:

  • toReversed()
  • toSpliced()
  • with()

These help avoid accidental mutations, especially in frameworks like React.


Practical Example: Student Result Analysis

const students = [
    { name: "Alice", marks: 92 },
    { name: "Bob", marks: 68 },
    { name: "Charlie", marks: 81 },
    { name: "David", marks: 55 }
];

const passedStudents = students.filter(student => student.marks >= 60);

const studentNames = passedStudents.map(student => student.name);

const averageMarks =
    students.reduce((sum, student) => sum + student.marks, 0) / students.length;

console.log(passedStudents);
console.log(studentNames);
console.log(averageMarks);

Common Mistakes

❌ Using map() when you don't use the returned array.

❌ Modifying arrays unexpectedly with sort(), reverse(), or splice().

❌ Forgetting that objects are assigned by reference.

❌ Using for...in to iterate over arrays instead of for...of.

❌ Forgetting that filter() always returns an array, even if only one item matches.


Interview Questions

What is the difference between map() and forEach()?

  • map() returns a new transformed array.
  • forEach() executes a callback but returns undefined.

When should you use reduce()?

Use reduce() when you need to combine an array into a single value, such as a total, average, grouped object, or flattened structure.


What is the difference between Map and a plain object?

  • Map accepts keys of any type.
  • Map preserves insertion order and provides convenient methods like set(), get(), has(), and delete().
  • Plain objects are primarily designed for structured data with string or symbol keys.

Why use Set?

A Set automatically stores only unique values, making it useful for removing duplicates and membership checks.


Practice Exercises

  1. Find the highest and lowest numbers in an array.
  2. Remove duplicate values from an array.
  3. Sort an array of objects by age.
  4. Calculate the average salary of employees using reduce().
  5. Convert an array of user objects into an array of usernames using map().
  6. Filter products that cost more than ₹1000.
  7. Count how many times each word appears in an array.
  8. Merge two objects using the spread operator.
  9. Build a simple phone book using Map.
  10. Create a unique list of programming languages using Set.


This is where JavaScript becomes truly interactive. So far, you've learned how to write JavaScript programs. Now you'll learn how JavaScript communicates with web pages using the Document Object Model (DOM).

DOM manipulation is one of the most important skills for frontend development. Every modern framework—including React, Angular, Vue, and Svelte—is built on DOM concepts.

By the end of this section, you'll be able to build interactive web pages, validate forms, create dynamic content, handle user events, and store data in the browser.


What is the DOM?

The Document Object Model (DOM) is a programming interface that represents an HTML document as a tree of objects.

Instead of treating an HTML page as plain text, the browser converts it into a structure that JavaScript can read and modify.

For example, consider this HTML:

<!DOCTYPE html>
<html>
<head>
    <title>My Website</title>
</head>
<body>

<h1>Welcome</h1>

<p>Learning JavaScript</p>

</body>
</html>

The browser represents it like this:

Document
│
├── html
│
├── head
│   └── title
│
└── body
    ├── h1
    └── p

Every HTML element becomes a JavaScript object.


Why is the DOM Important?

Without the DOM, websites would remain static.

The DOM enables JavaScript to:

  • Change text
  • Change images
  • Change CSS styles
  • Add new HTML elements
  • Remove existing elements
  • Validate forms
  • Respond to button clicks
  • Animate elements
  • Build interactive applications

Modern websites rely heavily on these capabilities.


Selecting HTML Elements

Before changing an element, JavaScript must locate it.


getElementById()

HTML

<h1 id="title">JavaScript Guide</h1>

JavaScript

const heading = document.getElementById("title");

console.log(heading);

getElementsByClassName()

HTML

<p class="info">First</p>

<p class="info">Second</p>

JavaScript

const items = document.getElementsByClassName("info");

console.log(items);

Returns an HTMLCollection.


getElementsByTagName()

const paragraphs = document.getElementsByTagName("p");

console.log(paragraphs);

querySelector()

The most commonly used selector.

Selects the first matching element.

HTML

<div class="card">
    JavaScript
</div>

JavaScript

const card = document.querySelector(".card");

console.log(card);

querySelectorAll()

Returns all matching elements.

const cards = document.querySelectorAll(".card");

console.log(cards);

Output

NodeList(3)

Example

cards.forEach(card => {

console.log(card);

});

Reading Content

Suppose the HTML is:

<h1 id="title">

JavaScript Tutorial

</h1>

Read text

const title = document.getElementById("title");

console.log(title.textContent);

Output

JavaScript Tutorial

textContent vs innerText

Both return text, but they behave differently.

element.textContent
  • Returns all text
  • Includes hidden text
  • Faster
element.innerText
  • Returns visible text only
  • Respects CSS visibility
  • Slightly slower

In most situations, textContent is the better choice.


innerHTML

Returns HTML inside an element.

<div id="content">

<b>Hello</b>

</div>
const content = document.getElementById("content");

console.log(content.innerHTML);

Output

<b>Hello</b>

Updating HTML

content.innerHTML = "<h2>Updated Content</h2>";

⚠️ Security Tip: Avoid inserting untrusted user input directly with innerHTML, as it can lead to Cross-Site Scripting (XSS) vulnerabilities. Prefer textContent when you only need to display text.


Changing Text

const heading = document.querySelector("h1");

heading.textContent = "Modern JavaScript";

Before

JavaScript Guide

After

Modern JavaScript

Changing CSS Styles

const heading = document.querySelector("h1");

heading.style.color = "blue";

heading.style.fontSize = "40px";

heading.style.backgroundColor = "yellow";

Although inline styles work, using CSS classes is generally cleaner for larger projects.


Working with CSS Classes

Instead of directly modifying styles, use classList.

HTML

<div id="box" class="card">

Content

</div>

Add class

box.classList.add("active");

Remove class

box.classList.remove("active");

Toggle class

box.classList.toggle("dark");

Check class

box.classList.contains("card");

Output

true

Changing Attributes

HTML

<img id="logo" src="old.png">

JavaScript

const image = document.getElementById("logo");

image.setAttribute("src", "new.png");

Read attribute

console.log(image.getAttribute("src"));

Remove attribute

image.removeAttribute("src");

Creating HTML Elements

Create a paragraph

const paragraph = document.createElement("p");

paragraph.textContent = "This paragraph was created dynamically.";

Nothing appears yet because the element has not been added to the page.


Adding Elements

Append to body

document.body.appendChild(paragraph);

Append to another element

const container = document.querySelector(".container");

container.appendChild(paragraph);

insertAdjacentHTML()

Useful for inserting HTML without replacing existing content.

const list = document.querySelector("#list");

list.insertAdjacentHTML(
    "beforeend",
    "<li>New Item</li>"
);

Possible positions:

  • beforebegin
  • afterbegin
  • beforeend
  • afterend

Removing Elements

const element = document.querySelector(".old");

element.remove();

Replacing Elements

const oldElement = document.querySelector("#old");

const newElement = document.createElement("h2");

newElement.textContent = "New Heading";

oldElement.replaceWith(newElement);

Event Handling

Events allow JavaScript to respond to user actions.

Common events include:

  • click
  • dblclick
  • mouseover
  • mouseout
  • keydown
  • keyup
  • input
  • submit
  • change
  • focus
  • blur

Click Event

HTML

<button id="btn">

Click Me

</button>

JavaScript

const button = document.getElementById("btn");

button.addEventListener("click", function(){

console.log("Button Clicked");

});

Output after clicking

Button Clicked

Arrow Function Event

button.addEventListener("click", ()=>{

alert("Welcome!");

});

Mouse Events

const box = document.querySelector(".box");

box.addEventListener("mouseover", ()=>{

console.log("Mouse Entered");

});

box.addEventListener("mouseout", ()=>{

console.log("Mouse Left");

});

Keyboard Events

document.addEventListener("keydown", (event)=>{

console.log(event.key);

});

Pressing

A

Outputs

a

Useful properties:

  • event.key
  • event.code
  • event.ctrlKey
  • event.shiftKey
  • event.altKey

Input Event

<input id="username">
const input = document.getElementById("username");

input.addEventListener("input",(event)=>{

console.log(event.target.value);

});

This updates every time the user types.


Form Handling

HTML

<form id="loginForm">

<input
type="text"
id="name">

<button>

Submit

</button>

</form>

JavaScript

const form = document.getElementById("loginForm");

form.addEventListener("submit",(event)=>{

event.preventDefault();

console.log("Form Submitted");

});

event.preventDefault() prevents the browser from reloading the page.


Basic Form Validation

const nameInput = document.getElementById("name");

if(nameInput.value.trim()===""){

alert("Name Required");

}

More complete example:

form.addEventListener("submit", (event) => {
    event.preventDefault();

    const name = nameInput.value.trim();

    if (name === "") {
        alert("Please enter your name.");
        return;
    }

    console.log(`Welcome, ${name}!`);
});

Event Delegation

Instead of adding an event listener to every child element, attach one listener to the parent.

const list = document.querySelector("#todoList");

list.addEventListener("click", (event) => {
    if (event.target.matches("li")) {
        console.log(event.target.textContent);
    }
});

This approach improves performance when working with many dynamic elements.


DOM Traversal

Example HTML

<div id="parent">
    <p>First</p>
    <p>Second</p>
</div>

JavaScript

const parent = document.getElementById("parent");

console.log(parent.children);

console.log(parent.firstElementChild);

console.log(parent.lastElementChild);

Other useful properties:

element.parentElement

element.nextElementSibling

element.previousElementSibling

Local Storage

Local Storage stores data even after the browser closes.

Save

localStorage.setItem("username","Alice");

Read

console.log(localStorage.getItem("username"));

Delete one

localStorage.removeItem("username");

Delete everything

localStorage.clear();

Storing Objects in Local Storage

Since Local Storage stores strings, convert objects to JSON.

const user = {

name:"Alice",

age:25

};

localStorage.setItem(

"user",

JSON.stringify(user)

);

Retrieve

const storedUser = JSON.parse(

localStorage.getItem("user")

);

console.log(storedUser);

Session Storage

Works similarly to Local Storage but is cleared when the browser tab is closed.

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

console.log(sessionStorage.getItem("theme"));

Browser Timers

setTimeout()

Runs code once after a delay.

setTimeout(() => {
    console.log("Executed after 2 seconds");
}, 2000);

setInterval()

Runs repeatedly until stopped.

const timer = setInterval(() => {
    console.log("Tick");
}, 1000);

Stop it

clearInterval(timer);

Mini Project: Live Character Counter

HTML

<textarea id="message"></textarea>

<p>Characters: <span id="count">0</span></p>

JavaScript

const textarea = document.getElementById("message");

const count = document.getElementById("count");

textarea.addEventListener("input",()=>{

count.textContent = textarea.value.length;

});

Features

  • Live updates
  • Event handling
  • DOM manipulation
  • User interaction

Mini Project: Dark Mode Toggle

HTML

<button id="themeBtn">Toggle Theme</button>

JavaScript

const themeBtn = document.getElementById("themeBtn");

themeBtn.addEventListener("click", () => {
    document.body.classList.toggle("dark-mode");
});

CSS

.dark-mode {
    background-color: #222;
    color: white;
}

Common Mistakes

❌ Using innerHTML for plain text.

❌ Forgetting preventDefault() in form submissions.

❌ Adding hundreds of individual event listeners instead of using event delegation.

❌ Forgetting to parse JSON retrieved from Local Storage.

❌ Attempting to access DOM elements before they exist. Place your script at the end of the <body> or wait for the DOMContentLoaded event.


Interview Questions

What is the DOM?

A tree-like representation of an HTML document that JavaScript can manipulate.


Difference between querySelector() and querySelectorAll()?

  • querySelector() returns the first matching element.
  • querySelectorAll() returns a static NodeList of all matching elements.

What is event bubbling?

When an event starts at the target element and propagates upward through its ancestor elements.


Why use addEventListener()?

It allows multiple event listeners on the same element and separates JavaScript behavior from HTML markup.


Difference between Local Storage and Session Storage?

Local StorageSession Storage
Persists after browser restartCleared when the tab closes
Larger persistenceTemporary session data
Shared across tabs of the same originLimited to the current tab

Practice Exercises

  1. Build a digital clock.
  2. Create a color changer using buttons.
  3. Build a simple image gallery.
  4. Create a BMI calculator with form validation.
  5. Develop a to-do list using Local Storage.
  6. Implement a dark mode toggle that remembers the user's preference.
  7. Build a live search filter for a list of items.
  8. Create an accordion (expand/collapse sections).
  9. Implement a countdown timer using setInterval().
  10. Build a simple notes application that stores notes in Local Storage.

Asynchronous programming is one of the most important concepts in modern JavaScript. Every time you fetch data from a server, upload a file, process a payment, or interact with a cloud service, asynchronous code is involved.

Many beginners struggle with this topic because several concepts—such as the Call Stack, Web APIs, Callback Queue, Microtask Queue, and Event Loop—work together behind the scenes. In this part, we'll build these concepts step by step.


What is Synchronous Programming?

By default, JavaScript executes code one statement at a time in the order it appears.

Example:

console.log("Start");

console.log("Learning JavaScript");

console.log("End");

Output

Start
Learning JavaScript
End

Each line waits until the previous one has finished.


What is Asynchronous Programming?

Some operations take time to complete, such as:

  • Downloading data from a server
  • Reading files
  • Database queries
  • Waiting for user input
  • Timers
  • Image uploads
  • Video streaming
  • API requests

Instead of blocking the entire program, JavaScript allows these operations to run asynchronously.

Example

console.log("Start");

setTimeout(() => {
    console.log("Task Completed");
}, 2000);

console.log("End");

Output

Start
End
Task Completed

JavaScript continues executing other code while waiting for the timer.


Why JavaScript Can Be Asynchronous

JavaScript itself is single-threaded, meaning it executes one task at a time.

However, the browser (or Node.js runtime) provides additional capabilities such as:

  • Timers
  • Network requests
  • DOM events
  • File operations

These runtime features make asynchronous programming possible.


JavaScript Execution Model

Understanding how JavaScript executes code is essential.

               JavaScript Runtime

        ┌────────────────────────┐
        │       Call Stack       │
        └──────────┬─────────────┘
                   │
                   ▼
        ┌────────────────────────┐
        │      Web APIs          │
        │ setTimeout             │
        │ Fetch API              │
        │ DOM Events             │
        └──────────┬─────────────┘
                   │
                   ▼
        ┌────────────────────────┐
        │ Callback Queue         │
        └──────────┬─────────────┘
                   │
                   ▼
        ┌────────────────────────┐
        │ Microtask Queue        │
        │ Promises               │
        └──────────┬─────────────┘
                   │
                   ▼
              Event Loop
                   │
                   ▼
              Call Stack

Call Stack

The Call Stack keeps track of function execution.

Example

function first() {
    second();
}

function second() {
    third();
}

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

first();

Execution order

Call first()

↓

Call second()

↓

Call third()

↓

Print Hello

↓

Remove third()

↓

Remove second()

↓

Remove first()

The Call Stack follows the Last In, First Out (LIFO) principle.


Web APIs

The browser handles operations such as:

  • setTimeout()
  • fetch()
  • Mouse events
  • Keyboard events
  • Geolocation
  • DOM events

These APIs execute outside the JavaScript engine.

Example

setTimeout(() => {

console.log("Done");

},3000);

The timer runs inside the browser's Web API environment, not on the Call Stack.


Callback Queue

When an asynchronous task finishes, its callback is placed in the Callback Queue.

Example

setTimeout(() => {

console.log("Hello");

},1000);

Flow

Call Stack

↓

Web API

↓

Callback Queue

↓

Event Loop

↓

Call Stack

The callback executes only when the Call Stack becomes empty.


Event Loop

The Event Loop continuously checks:

  • Is the Call Stack empty?
  • If yes, move the next callback into the Call Stack.

Without the Event Loop, asynchronous JavaScript would not function correctly.


Microtask Queue

Promise callbacks have higher priority than the Callback Queue.

Example

console.log("Start");

setTimeout(() => {
    console.log("Timeout");
}, 0);

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

console.log("End");

Output

Start
End
Promise
Timeout

Even with a 0 ms timeout, Promise callbacks execute first because they are placed in the Microtask Queue.


Callback Functions

A callback is a function passed to another function to be executed later.

function greet(name, callback) {
    console.log(`Hello, ${name}`);
    callback();
}

function goodbye() {
    console.log("Goodbye!");
}

greet("Alice", goodbye);

Output

Hello, Alice
Goodbye!

Callback Hell

Deeply nested callbacks quickly become difficult to read.

loginUser(function(user){

getOrders(user,function(orders){

processPayment(orders,function(payment){

sendEmail(payment,function(){

console.log("Completed");

});

});

});

});

Problems:

  • Hard to read
  • Difficult to debug
  • Poor maintainability
  • Error handling becomes complex

Promises solve these issues.


Promises

A Promise represents a value that may be available now, later, or never if an error occurs.

Promise states:

Pending

↓

Fulfilled

or

Rejected

Creating a Promise

const promise = new Promise((resolve, reject) => {

const success = true;

if(success){

resolve("Operation Successful");

}

else{

reject("Operation Failed");

}

});

Consuming a Promise

promise
.then(result => {

console.log(result);

})
.catch(error => {

console.log(error);

});

Output

Operation Successful

Promise Chaining

Promise.resolve(5)

.then(number => number * 2)

.then(number => number + 10)

.then(result => console.log(result));

Output

20

Each .then() receives the value returned by the previous one.


Promise.finally()

finally() runs regardless of whether the Promise succeeds or fails.

fetch("/api/users")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error))
    .finally(() => {
        console.log("Request finished");
    });

async Functions

async makes working with Promises easier.

async function greet(){

return "Hello";

}

An async function always returns a Promise.

greet().then(console.log);

Output

Hello

await

await pauses execution inside an async function until a Promise resolves.

function delay(){

return new Promise(resolve=>{

setTimeout(resolve,2000);

});

}

async function run(){

console.log("Waiting...");

await delay();

console.log("Completed");

}

run();

Output

Waiting...

Completed

Fetch API

The Fetch API is the modern way to make HTTP requests.

Basic syntax

fetch(url)

Fetching Data

fetch("https://jsonplaceholder.typicode.com/users")

.then(response=>response.json())

.then(data=>{

console.log(data);

});

The response is converted to JSON before being used.


Using async/await with Fetch

async function getUsers(){

const response = await fetch(

"https://jsonplaceholder.typicode.com/users"

);

const users = await response.json();

console.log(users);

}

getUsers();

This style is cleaner and easier to read than long Promise chains.


Handling Fetch Errors

Always handle errors when working with APIs.

async function loadUsers() {
    try {
        const response = await fetch("https://jsonplaceholder.typicode.com/users");

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

        const users = await response.json();

        console.log(users);
    } catch (error) {
        console.error("Failed to load users:", error.message);
    }
}

Understanding JSON

JSON (JavaScript Object Notation) is a lightweight data format used for communication between applications.

JSON

{
  "name": "Alice",
  "age": 25,
  "city": "London"
}

JavaScript Object

const user = {

name:"Alice",

age:25,

city:"London"

};

JSON.stringify()

Convert an object into JSON.

const user = {

name:"Alice",

age:25

};

console.log(JSON.stringify(user));

Output

{"name":"Alice","age":25}

JSON.parse()

Convert JSON back into an object.

const json =

'{"name":"Alice","age":25}';

const user = JSON.parse(json);

console.log(user);

HTTP Methods

MethodPurpose
GETRetrieve data
POSTCreate data
PUTReplace existing data
PATCHUpdate part of existing data
DELETERemove data

Sending POST Requests

fetch("https://jsonplaceholder.typicode.com/posts", {
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        title: "JavaScript",
        body: "Modern Guide",
        userId: 1
    })
})
.then(response => response.json())
.then(data => console.log(data));

Promise Utility Methods

Promise.all()

Runs multiple Promises in parallel.

const p1 = Promise.resolve("HTML");
const p2 = Promise.resolve("CSS");
const p3 = Promise.resolve("JavaScript");

Promise.all([p1, p2, p3])
    .then(values => console.log(values));

Output

["HTML", "CSS", "JavaScript"]

Promise.allSettled()

Waits for every Promise to finish, regardless of success or failure.

Promise.allSettled([
    Promise.resolve("Success"),
    Promise.reject("Failure")
]).then(results => console.log(results));

Promise.race()

Returns the first settled Promise.

Promise.race([
    fetch("/fast-api"),
    fetch("/slow-api")
]).then(result => console.log(result));

Promise.any()

Returns the first successfully fulfilled Promise and ignores rejected ones until a success occurs.


AbortController

Cancel an ongoing Fetch request.

const controller = new AbortController();

fetch("https://jsonplaceholder.typicode.com/users", {
    signal: controller.signal
});

controller.abort();

Useful for search suggestions and preventing unnecessary network requests.


Practical Project: Random User Viewer

async function loadRandomUser() {
    try {
        const response = await fetch("https://randomuser.me/api/");
        const data = await response.json();

        const user = data.results[0];

        console.log(user.name.first, user.name.last);
        console.log(user.email);
    } catch (error) {
        console.error(error);
    }
}

loadRandomUser();

Practical Project: Weather App Flow

User enters city

↓

Click Search

↓

Fetch Weather API

↓

Receive JSON

↓

Extract temperature

↓

Update DOM

↓

Display Weather

Common Mistakes

❌ Forgetting to use await before asynchronous operations.

❌ Ignoring response.ok and assuming every request succeeds.

❌ Mixing callbacks, Promises, and async/await unnecessarily in the same code.

❌ Forgetting to return a Promise inside a .then() callback.

❌ Not wrapping await operations in try...catch when errors are possible.


Interview Questions

What is asynchronous programming?

A programming model that allows long-running operations to execute without blocking the main thread.


What is the Event Loop?

The Event Loop monitors the Call Stack and moves completed asynchronous callbacks or microtasks into it when it becomes empty.


Difference between callbacks and Promises?

  • Callbacks can lead to deeply nested code.
  • Promises provide cleaner chaining and better error handling.

Why use async/await?

It makes asynchronous code easier to read and maintain while still working with Promises under the hood.


What is the Fetch API?

A modern browser API for making HTTP requests and interacting with web services.


Practice Exercises

  1. Fetch and display users from a public API.
  2. Build a weather application using a weather API.
  3. Create a random quote generator.
  4. Build a GitHub user profile search tool.
  5. Implement infinite scrolling using asynchronous requests.
  6. Fetch and display blog posts from a REST API.
  7. Build a live currency converter using an exchange-rate API.
  8. Use Promise.all() to load multiple resources simultaneously.
  9. Add loading indicators and error messages to an API-driven application.
  10. Implement request cancellation with AbortController.

Congratulations! You've reached the final part of this complete JavaScript guide. In this section, we'll cover production-level JavaScript concepts used in modern applications, including modules, object-oriented programming, error handling, regular expressions, dates, internationalization, performance optimization, testing basics, build tools, deployment, and a collection of real-world projects.


JavaScript Modules (ES Modules)

As applications grow, placing all code in a single file becomes difficult to manage. ES Modules allow you to split your code into reusable files.

Exporting

math.js

export function add(a, b) {
    return a + b;
}

export const PI = 3.1415926535;

Importing

app.js

import { add, PI } from "./math.js";

console.log(add(10, 20));
console.log(PI);

Output

30
3.1415926535

Default Export

export default function greet() {
    console.log("Welcome");
}

Import

import greet from "./greet.js";

greet();

Object-Oriented Programming (OOP)

JavaScript supports object-oriented programming through classes.


Creating a Class

class Student {

    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    introduce() {
        console.log(`Hi, I'm ${this.name}`);
    }

}

const student = new Student("Alice", 22);

student.introduce();

Output

Hi, I'm Alice

Inheritance

class Animal {

    speak() {
        console.log("Animal Sound");
    }

}

class Dog extends Animal {

    speak() {
        console.log("Bark");
    }

}

const dog = new Dog();

dog.speak();

Output

Bark

Getters and Setters

class Employee {

    constructor(name) {
        this._name = name;
    }

    get name() {
        return this._name;
    }

    set name(value) {
        this._name = value;
    }

}

const emp = new Employee("John");

console.log(emp.name);

emp.name = "Alice";

console.log(emp.name);

Static Methods

class Calculator {

    static add(a, b) {
        return a + b;
    }

}

console.log(Calculator.add(5, 8));

Private Class Fields

Modern JavaScript supports truly private fields.

class BankAccount {

    #balance = 0;

    deposit(amount) {
        this.#balance += amount;
    }

    getBalance() {
        return this.#balance;
    }

}

const account = new BankAccount();

account.deposit(500);

console.log(account.getBalance());

Error Handling

Applications should never crash unexpectedly.


try...catch

try {

    let result = 10 / 0;

    console.log(result);

}
catch(error) {

    console.log(error);

}

Throwing Errors

function divide(a, b) {

    if (b === 0) {
        throw new Error("Division by zero is not allowed.");
    }

    return a / b;

}

try {

    console.log(divide(10, 0));

}
catch(error) {

    console.log(error.message);

}

Custom Error Classes

class ValidationError extends Error {

    constructor(message) {
        super(message);
        this.name = "ValidationError";
    }

}

throw new ValidationError("Invalid Email");

Regular Expressions (RegExp)

Regular expressions help search and validate text.


Testing Email

const email = "user@example.com";

const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

console.log(pattern.test(email));

Output

true

Extract Numbers

const text = "Order ID: 4589";

const numbers = text.match(/\d+/g);

console.log(numbers);

Output

["4589"]

Working with Dates

const today = new Date();

console.log(today);

Formatting Dates

console.log(today.getFullYear());

console.log(today.getMonth() + 1);

console.log(today.getDate());

Internationalization API

Display dates and currency according to locale.

const amount = 125000;

const formatter = new Intl.NumberFormat("en-IN", {
    style: "currency",
    currency: "INR"
});

console.log(formatter.format(amount));

Output

₹1,25,000.00

Optional Chaining Review

const user = {
    profile: {
        name: "Alice"
    }
};

console.log(user.profile?.name);

console.log(user.address?.city);

Nullish Coalescing Review

const username = null;

console.log(username ?? "Guest");

Performance Optimization

Modern JavaScript applications should be optimized for speed.

Best practices:

  • Use const by default.
  • Minimize unnecessary DOM updates.
  • Cache frequently accessed DOM elements.
  • Use event delegation.
  • Debounce expensive operations.
  • Throttle scroll and resize events.
  • Lazy-load images and modules.
  • Avoid blocking the main thread with heavy computations.

Debouncing

Useful for search boxes.

function debounce(callback, delay) {

    let timer;

    return (...args) => {

        clearTimeout(timer);

        timer = setTimeout(() => {
            callback(...args);
        }, delay);

    };

}

Throttling

Useful for scrolling.

function throttle(callback, delay) {

    let waiting = false;

    return (...args) => {

        if (waiting) return;

        callback(...args);

        waiting = true;

        setTimeout(() => {
            waiting = false;
        }, delay);

    };

}

Web Workers

Heavy calculations can block the UI.

Web Workers allow computation in a background thread.

worker.js

self.onmessage = function(event) {

    const result = event.data * 2;

    postMessage(result);

};

Main file

const worker = new Worker("worker.js");

worker.postMessage(10);

worker.onmessage = event => {

    console.log(event.data);

};

Testing Basics

Testing improves software quality.

Popular frameworks:

  • Jest
  • Vitest
  • Mocha
  • Cypress (End-to-End)
  • Playwright (End-to-End)

Example

function add(a,b){

return a+b;

}

test("Addition",()=>{

expect(add(5,2)).toBe(7);

});

Build Tools

Modern JavaScript projects commonly use:

ToolPurpose
ViteFast frontend development
WebpackBundling
ParcelZero-configuration bundler
RollupLibrary bundling
BabelJavaScript transpilation
ESLintCode quality
PrettierCode formatting
npmPackage management
pnpmFast package manager
YarnAlternative package manager

JavaScript Project Folder Structure

project/
│
├── index.html
├── package.json
├── src/
│   ├── app.js
│   ├── utils.js
│   ├── api.js
│   ├── components/
│   └── styles/
│
├── public/
│
├── assets/
│
└── tests/

Real-World JavaScript Projects

To become job-ready, build practical applications.

Beginner Projects

  • Digital Clock
  • Calculator
  • To-Do List
  • Counter App
  • Random Quote Generator
  • Password Generator
  • BMI Calculator
  • Stopwatch
  • Image Slider
  • Notes App

Intermediate Projects

  • Weather Dashboard
  • Expense Tracker
  • Movie Search App
  • Currency Converter
  • Quiz Application
  • Blog CMS Frontend
  • Markdown Editor
  • Music Player
  • Kanban Board
  • Chat Application (Frontend)

Advanced Projects

  • E-commerce Store
  • Video Streaming UI
  • Real-Time Chat using WebSockets
  • Project Management Dashboard
  • AI Chat Interface
  • GitHub Repository Explorer
  • Collaborative Whiteboard
  • Online Code Editor
  • File Manager
  • Progressive Web App (PWA)

JavaScript Interview Preparation

Frequently asked interview topics:

  • Hoisting
  • Closures
  • Event Loop
  • Call Stack
  • Promises
  • async/await
  • Prototype Inheritance
  • this keyword
  • Arrow Functions
  • Event Delegation
  • DOM Manipulation
  • Array Methods
  • Modules
  • Classes
  • REST APIs
  • Fetch API
  • Local Storage
  • Session Storage
  • Debouncing
  • Throttling
  • Memory Leaks
  • Garbage Collection

Best Practices for Writing Modern JavaScript

  • Use const whenever possible.
  • Use let only when reassignment is required.
  • Prefer === over ==.
  • Write small, reusable functions.
  • Keep functions focused on one responsibility.
  • Use descriptive variable names.
  • Avoid unnecessary global variables.
  • Handle asynchronous errors with try...catch.
  • Validate user input.
  • Use modules to organize code.
  • Format code consistently with Prettier.
  • Lint your code with ESLint.
  • Write unit tests for critical logic.
  • Avoid mutating data unnecessarily.
  • Keep dependencies up to date.

JavaScript Learning Roadmap (2026)

HTML
   │
   ▼
CSS
   │
   ▼
JavaScript Basics
   │
   ▼
ES6+
   │
   ▼
DOM Manipulation
   │
   ▼
Async JavaScript
   │
   ▼
REST APIs
   │
   ▼
Git & GitHub
   │
   ▼
Node.js
   │
   ▼
React / Vue / Angular
   │
   ▼
TypeScript
   │
   ▼
Testing
   │
   ▼
Build Tools
   │
   ▼
Deployment

Frequently Asked Questions (FAQ)

Is JavaScript worth learning in 2026?

Yes. JavaScript remains one of the most widely used programming languages and is essential for modern web development, powering everything from interactive websites to full-stack applications.


How long does it take to learn JavaScript?

  • Basics: 4–6 weeks
  • Intermediate concepts: 2–3 months
  • Professional proficiency: 6–12 months with consistent practice and project building.

Should I learn JavaScript before React?

Absolutely. React builds upon core JavaScript concepts such as functions, objects, arrays, ES6 modules, asynchronous programming, and DOM interactions.


Is JavaScript enough for backend development?

Yes. Using Node.js, JavaScript can be used to build APIs, authentication systems, real-time applications, and scalable backend services.


What should I learn after JavaScript?

A recommended path is:

  • TypeScript
  • Node.js & Express
  • React (or Vue/Angular)
  • Databases (PostgreSQL, MongoDB)
  • Git & GitHub
  • Docker
  • Testing (Jest/Playwright)
  • CI/CD and cloud deployment

Conclusion

JavaScript has evolved into one of the most versatile and influential programming languages in software development. From simple browser interactions to enterprise-scale web applications, backend services, mobile apps, desktop software, and AI-powered experiences, JavaScript continues to expand its reach.

The key to mastering JavaScript isn't memorizing syntax—it's consistently building projects that reinforce the concepts you've learned. Start with small applications like a calculator or to-do list, then gradually move toward API-driven apps, dashboards, and full-stack projects. Each project will deepen your understanding of core concepts such as asynchronous programming, modular architecture, and clean code practices.

By completing this guide, you've covered the essential knowledge expected of a modern JavaScript developer in 2026. Continue practicing, stay current with new ECMAScript features, and build a portfolio that demonstrates your skills through real-world applications.


Post a Comment

Previous Post Next Post