# JavaScript

**JavaScript (JS)** is a **high-level, interpreted programming language** primarily used to make **web pages interactive**. It is one of the **core technologies of the web**, along with HTML and CSS.

> <mark>High level :</mark> J**avaScript is closer to human language**  
> **<mark>Interpreted : </mark>** the **code is run line-by-line by an interpreter** ( the browser's JavaScript engine like V8 in Chrome).

### Use Cases of JavaScript

| **Domain** | **What JavaScript Can Do** |
| --- | --- |
| **Frontend Web Development :** | Make websites interactive: forms, animations, popups, dynamic content. |
| **Backend Development (Node.js) :** | Build full server-side applications: APIs, authentication, databases. |
| **Mobile App Development :** | Frameworks like **React Native**, **Ionic**, and **NativeScript** use JS to build cross-platform apps. |
| D**esktop Applications :** | Build desktop apps using **Electron.js** (e.g., VS Code, Slack). |
| **Game Development :** | Use engines like **Phaser.js** or **Three.js** for 2D/3D browser games. |
| **Data Visualization :** | Libraries like **Chart.js**, **D3.js** let you visualize data interactively. |
| **Machine Learning in JS :** | Libraries like **TensorFlow.js** enable ML in the browser. |
| **Automation & Scripting :** | Automate browser tasks with tools like **Puppeteer**, **Playwright**. |

---

## Variables

variables are like a container which are used to store something that will be needed repeatedly.

In JS, we have 3 types of variables :  
1\. Var  
2\. Let  
3\. Const

### 1\. `var`

* Introduced in **ES5** (old way).
    
* **Function-scoped**.
    
* **Can be redeclared and reassigned**.
    
* **Hoisted** (moved to the top during execution, but not initialized).
    

**Syntax:**

```javascript
var name = "Koustav";
console.log(name);  // koustav
//-----------------------
var num = 10;
console.log(num);  // 10

var num=20;
console.log(num);   // 20
//-----------------------
{
var n = 50;
}
console.log(n);   // 50 
// ----------------------
function greet() {
  var msg = "Hello";
  if (true) {
    var msg = "Hi"; // Same variable (due to function scope)
    console.log(msg); // Hi
  }
  console.log(msg); // Hi
}
greet();
```

### 2\. `let`

* Introduced in **ES6**.
    
* **Block-scoped**.
    
* **Can be reassigned** but **not redeclared** in the same scope.
    
* **Hoisted** but not initialized (you get a `ReferenceError` if used before declaration).
    

**Syntax**:

```javascript
let age = 25;
//-------------------------
let num = 10;
console.log(num);  // 10

let num = 20;
console.log(num);   // error - num is already defined - cannot re-declared

num = 20;
console.log(num);   // this will work as it can be re-assigned 
//-------------------------

function test() {
  let x = 10;
  if (true) {
    let x = 20; // different variable (block scope)
    console.log(x); // 20
  }
  console.log(x); // 10
}
test();
```

### 3\. `const`

* Also introduced in **ES6**.
    
* **Block-scoped** like `let`.
    
* **Cannot be reassigned**.
    
* Must be **initialized at the time of declaration**.
    

**Syntax**:

```javascript
const pi = 3.14;
// --------------------

const user = { name: "Koustav" };
user.name = "Moitra"; // Allowed (object property changed)
console.log(user.name); // Moitra

user = { name: "New" }; // ❌ Error: Assignment to constant variable
// --------------------

// Use for constants or when reassignment is not needed.
// For objects/arrays, internal values can be changed
```

**Summary Table:**

| **Feature** | `var` | `let` | `const` |
| --- | --- | --- | --- |
| Scope | Function | Block | Block |
| Hoisting | Yes (undefined) | Yes (no access) | Yes (no access) |
| Reassignment | ✅ Yes | ✅ Yes | ❌ No |
| Redeclaration | ✅ Yes | ❌ No | ❌ No |
| Initialization | Optional | Optional | Mandatory |

---

## Hoisting

**Hoisting** is JavaScript's default behavior of **moving declarations to the top of the current scope** (before code execution).

**<mark>Hoisting with </mark>** `var`

```javascript
console.log(name); // undefined
var name = "Koustav";
```

**Explanation:**

During the memory phase, `var name` is hoisted to the top and initialized as `undefined`. So by the time `console.log()` runs, `name` exists but has no value yet.

Internally, JS sees it like:

```javascript
var name;
console.log(name); // undefined
name = "Koustav";
```

`let` **<mark>and </mark>** `const` **<mark>are hoisted but not initialized</mark>**

```javascript
console.log(age); // ❌ ReferenceError
let age = 25;
```

Why?

* `let` and `const` are hoisted but kept in a **Temporal Dead Zone (TDZ)** from the start of the block until they are initialized.
    
* You **can’t access them before declaration**.
    

**<mark>Function Declaration Hoisting</mark>**

```javascript
greet(); // ✅ Works

function greet() {
  console.log("Hello, Koustav!");
}
```

**Why?**

* **Function declarations are fully hoisted**, including their body.
    

JS treats it like:

```javascript
function greet() {
  console.log("Hello, Koustav!");
}
greet();
```

**<mark>Function Expression is not hoisted</mark>**

```javascript
sayHi(); // ❌ TypeError: sayHi is not a function

var sayHi = function () {
  console.log("Hi!");
};
```

Why?

* `sayHi` is hoisted as a variable (`undefined`), but the **function body is not** hoisted.
    
* You’re trying to call `undefined()`.
    

---

## **Temporal Dead Zone (TDZ)**

The **Temporal Dead Zone (TDZ)** is the time **between**:

* When a variable is **hoisted** (declared in memory), and
    
* When it is **actually initialized** in your code.
    

If you try to access the variable **before it’s initialized**, you’ll get a **ReferenceError** — even though it's hoisted.

TDZ applies to:

* `let`
    
* `const`
    

> ❌ Not to `var` (it gets `undefined` instead)

**Example:**

```javascript
console.log(name); // ❌ ReferenceError
let name = "Koustav";
```

**Why this error?**

* `let name` is hoisted to the top.
    
* But it’s not initialized until the `let` line is executed.
    
* So `console.log(name)` is trying to access it while it's still in the **TDZ**.
    

**Behind the scenes:**

JavaScript sees your code like:

```javascript
// TDZ starts here
let name; // declared (hoisted), but NOT initialized

console.log(name); // in TDZ → ReferenceError
name = "Koustav"; // TDZ ends here
```

**Best Practices to Avoid TDZ Issues:**

* ✅ Always **declare variables at the top** of their block.
    
* ✅ Never **use variables before declaring them**.
    
* ❌ Avoid mixing `var`, `let`, and `const` in the same scope.
    

---

## Template Literals

**Template Literals** are a new way to define strings introduced in **ES6 (ECMAScript 2015)**.

Instead of using:

* **Single quotes (**`'`)
    
* **Double quotes (**`"`)
    

You use **backticks (**`` ` ``).

**<mark>1. Basic Example:</mark>**

```javascript
let name = "Koustav";
let msg = `Hello, ${name}!`;
console.log(msg); // Hello, Koustav!
```

**<mark>2. Expression Interpolation:</mark>**

```javascript
let a = 10;
let b = 20;
console.log(`The sum of ${a} and ${b} is ${a + b}.`);
// Output: The sum of 10 and 20 is 30.
```

✅ You can even run JavaScript expressions inside `${}`.

**<mark>3. Multi-line Strings:</mark>**

```javascript
let poem = `Roses are red,
Violets are blue,
Template literals,
Make strings new.`;

console.log(poem);
/*
Roses are red,
Violets are blue,
Template literals,
Make strings new.
*/
```

✅ No need to use `\n` or `+` for line breaks!

**<mark>Before Template Literals (Old Way):</mark>**

```javascript
let name = "Koustav";
let msg = "Hello, " + name + "!";
```

**<mark>Now with Template Literals:</mark>**

```javascript
let msg = `Hello, ${name}!`;
```

---

## Data Type

JavaScript is a **dynamically typed language**, meaning:

> You don’t need to declare a variable’s type — it’s determined at runtime.

| **Category** | **Data Types** |
| --- | --- |
| **Primitive** | String, Number, Boolean, Null, Undefined, Symbol, BigInt |
| **Non-Primitive** | Object (includes arrays, functions, dates, etc.) |

| **Feature** | **Primitive** | **Non-Primitive (Reference)** |
| --- | --- | --- |
| **Stored as** | Value | Reference (Memory Address) |
| **Mutable** | ❌ No | ✅ Yes |
| **Compared by** | Value | Reference |
| **Examples** | `"Hello"`, `42`, `true` | `{}`, `[]`, `function() {}` |
| **Memory Efficient** | More | Less (because of references) |

### 1\. **String**

Represents **text**.

```javascript
let name = "Koustav";
let greeting = 'Hello';
let sentence = `Welcome, ${name}`; // template literal
```

Strings can use:

* Double quotes `" "`
    
* Single quotes `' '`
    
* Backticks (for template literals)
    

### 2\. **Number**

Represents **any number**, whether integer or floating-point.

```javascript
let age = 25;
let price = 99.99;
let hex = 0xff;  // hexadecimal
```

JavaScript has only **one number type**, unlike other languages.

### 3\. **BigInt**

Used for very large integers beyond the `Number` limit.

```javascript
let bigNum = 1234567890123456789012345678901234567890n;
```

Note the `n` at the end.

### 4\. **Boolean**

Represents **true or false**.

```javascript
let isLoggedIn = true;
let hasPermission = false;
```

Commonly used in conditions and comparisons.

### 5\. **Undefined**

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

```javascript
let x;
console.log(x); // undefined
```

### 6\. **Null**

Represents **intentional absence of value**.

```javascript
let data = null;
```

Often used to **reset** a variable or indicate "nothing".

### 7\. **Symbol**

Used for creating **unique identifiers** (mainly in advanced coding or libraries).

```javascript
let id = Symbol("userID");
```

Symbols are **always unique**, even with the same description.

### 8\. **Object**

Used to store **collections of data** or **complex entities**.

```javascript
let user = {
  name: "Koustav",
  age: 25,
  isAdmin: true
};
```

Arrays, functions, and even dates are **objects** in JavaScript.

## Special Object Types

| Type | Description | Example |
| --- | --- | --- |
| Array | Ordered collection | `[1, 2, 3]` |
| Function | Block of code that can be called | `function() {}` |
| Date | Handles dates and times | `new Date()` |
| RegExp | Pattern for matching text | `/[a-z]/` |

## `typeof` Operator

Use `typeof` to check the data type:

```javascript
typeof "Hello"       // "string"
typeof 42            // "number"
typeof true          // "boolean"
typeof undefined     // "undefined"
typeof null          // ❗️"object" (this is a JavaScript quirk)
typeof Symbol()      // "symbol"
typeof {}            // "object"
typeof []            // "object"
typeof function(){}  // "function"
```

---

## Operators

**Operators** are special symbols or keywords used to perform operations on **operands** (values and variables).

```javascript
let sum = 10 + 5;  // '+' is the operator; 10 and 5 are operands
```

| **Type** | **Operators** |
| --- | --- |
| Arithmetic | `+`, `-`, `*`, `/`, `%`, `**`, `++`, `--` |
| Assignment | `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `**=` |
| Comparison | `==`, `===`, `!=`, `!==`, `<`, `>`, `<=`, `>=` |
| Logical | `&&`, `||`, `!` |
| String | `+` (concatenation) |
| Conditional | `? :` (ternary) |
| Type | `typeof`, `instanceof` |

---

## Type Coercion

**Type Coercion** in JavaScript is the **automatic or implicit conversion** of values from one data type to another.

It happens **when you perform operations** on mismatched data types — like adding a string and a number.

**1\. Implicit Coercion**

JavaScript **automatically converts** one data type to another.

```javascript
console.log("5" + 1); // "51" → number 1 is coerced to string
console.log("5" - 1); // 4   → string "5" is coerced to number
```

**2\. Explicit Coercion**

You **manually convert** a value using functions like `Number()`, `String()`, or `Boolean()`.

```javascript
let a = "42";
let b = Number(a); // Explicit coercion from string to number
console.log(b);    // 42
```

**<mark>1. Number + String</mark>**

```javascript
console.log(10 + "5");      // "105" (Number → String → Concatenation)
console.log("5" + 10);      // "510"
console.log("10" + true);   // "10true"
console.log("10" + null);   // "10null"
console.log("10" + undefined); // "10undefined"
```

➡️ The `+` operator **prefers string** if one of the operands is a string.

**<mark>2. Number - String / Boolean / Null / Undefined</mark>**

```javascript
console.log("10" - 5);      // 5   → String to Number
console.log(true - 1);      // 0   → true → 1
console.log(false - 1);     // -1  → false → 0
console.log(null - 1);      // -1  → null → 0
console.log(undefined - 1); // NaN → undefined → NaN
```

➡️ `-`, `*`, `/` → always try to convert values to **Number**.

**<mark>3. String - String / Boolean / Null / Object</mark>**

```javascript
console.log("10" - "5");     // 5
console.log("hello" - "hi"); // NaN (non-numeric strings)
console.log("5" - true);     // 4
console.log("5" - null);     // 5
```

➡️ String gets coerced to number **only if it’s numeric**.

**<mark>4. Boolean + Number / String</mark>**

```javascript
console.log(true + 2);       // 3
console.log(false + 3);      // 3
console.log(true + "2");     // "true2"
console.log(false + "3");    // "false3"
```

➡️ Boolean → `true` becomes `1`, `false` becomes `0`.

**<mark>5. null and undefined</mark>**

```javascript
console.log(null + 5);        // 5       → null → 0
console.log(undefined + 5);   // NaN     → undefined → NaN
console.log(null == undefined); // true (only in loose equality)
console.log(null === undefined); // false (different types)
```

**<mark>6. Array or Object + Number/String</mark>**

```javascript
console.log([] + 1);          // "1"       → [] → ""
console.log([1] + 1);         // "11"      → [1] → "1"
console.log({} + 1);          // "[object Object]1"
console.log([] - 1);          // -1        → [] → 0
```

➡️ Arrays and objects are coerced to strings like `""` or `"[object Object]"`.

**<mark>7. Special </mark>** `NaN` **<mark> Cases</mark>**

```javascript
console.log(NaN + 1);         // NaN
console.log(NaN - 1);         // NaN
console.log(NaN * 2);         // NaN
console.log(NaN === NaN);     // false → NaN is not equal to anything, even itself
```

**<mark>8. Arithmetic with Booleans</mark>**

```javascript
console.log(true * 3);        // 3
console.log(false / 2);       // 0
console.log(true * false);    // 0
```

**<mark>9. Truthy &amp; Falsy in Arithmetic</mark>**

**Falsy values**: `false`, `0`, `""`, `null`, `undefined`, `NaN`

```javascript
console.log("" + 1);         // "1"
console.log(0 + "0");        // "00"
console.log(false + true);   // 1
console.log(null + true);    // 1
```

**<mark>10. Unary + operator (Explicit conversion to Number)</mark>**

```javascript
console.log(+"5");           // 5
console.log(+true);          // 1
console.log(+false);         // 0
console.log(+null);          // 0
console.log(+undefined);     // NaN
```

---

## Conditional Statements

Conditional statements allow your code to **make decisions** and execute **different blocks of code** based on **conditions (true/false)**.

**<mark>1. </mark>** `if` **<mark> Statement</mark>**

**Syntax:**

```javascript
if (condition) {
  // code to execute if condition is true
}
```

**Example:**

```javascript
let age = 18;

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

**<mark>2. </mark>** `if...else` **<mark> Statement</mark>**

**Syntax**:

```javascript
if (condition) {
  // if true
} else {
  // if false
}
```

**Example**:

```javascript
let marks = 40;

if (marks >= 50) {
  console.log("You passed.");
} else {
  console.log("You failed.");
}
```

**<mark>3. </mark>** `if...else if...else` **<mark> Statement</mark>**

**Syntax**:

```javascript
if (condition1) {
  // block 1
} else if (condition2) {
  // block 2
} else {
  // default block
}
```

**Example**:

```javascript
let score = 85;

if (score >= 90) {
  console.log("Grade A");
} else if (score >= 80) {
  console.log("Grade B");
} else {
  console.log("Grade C");
}
```

**<mark>4. </mark>** `switch` **<mark> Statement</mark>**

Used when you have multiple conditions based on **one variable**.

**Syntax:**

```javascript
switch (expression) {
  case value1:
    // block
    break;
  case value2:
    // block
    break;
  default:
    // default block
}
```

**Example:**

```javascript
let day = "Tuesday";

switch (day) {
  case "Monday":
    console.log("Start of the week");
    break;
  case "Tuesday":
    console.log("Second day of the week");
    break;
  default:
    console.log("Some other day");
}
```

**<mark>5. Ternary Operator (</mark>**`? :`**<mark>)</mark>**

A **short-hand** for `if...else`.

**Syntax:**

```javascript
condition ? expression_if_true : expression_if_false;
```

**Example:**

```javascript
let age = 20;

let result = (age >= 18) ? "Adult" : "Minor";
console.log(result); // "Adult"
```

**<mark>Nested Conditionals</mark>**

**Example:**

```javascript
let num = 5;

if (num > 0) {
  if (num % 2 === 0) {
    console.log("Positive even number");
  } else {
    console.log("Positive odd number");
  }
}
```

**Summary Table**

| **Statement** | **Use Case** | **Short Note** |
| --- | --- | --- |
| `if` | One condition | Simple true/false check |
| `if...else` | Two outcomes | True → one block, False → another |
| `else if` | Multiple conditions | Used for checking multiple cases |
| `switch` | One variable, multiple fixed values | Good alternative to `else if` chain |
| `ternary` | Simple one-line decision | Short-hand for `if...else` |

---

## Loop

**Loops** are used to **execute a block of code repeatedly** as long as a certain condition is true.

**<mark>1. </mark>** `for` **<mark> Loop</mark>**

**Syntax:**

```javascript
for (initialization; condition; update) {
  // code block to execute
}
```

**Example:**

```javascript
for (let i = 1; i <= 5; i++) {
  console.log("Number: " + i);
}
/*
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
+/
```

**<mark>2. </mark>** `while` **<mark> Loop</mark>**

**Syntax:**

```javascript
while (condition) {
  // code block
}
```

**Example:**

```javascript
let i = 1;
while (i <= 3) {
  console.log("Hello");
  i++;
}

/* 
Hello
Hello
Hello
+/
```

**3\.** `do...while` **Loop**

Executes the block **at least once**, then checks the condition.

**Syntax:**

```javascript
do {
  // code block
} while (condition);
```

**Example:**

```javascript
let i = 1;
do {
  console.log("Value is: " + i);
  i++;
} while (i <= 2);

/*
Value is: 1
Value is: 2
+/
```

**<mark>4. </mark>** `for...in` **<mark> Loop</mark>**

Used to **iterate over object properties**.

**Example**:

```javascript
const person = { name: "Alice", age: 25 };

for (let key in person) {
  console.log(key + ": " + person[key]);
}

/* 
name: Alice
age: 25
*/
```

**<mark>5. </mark>** `for...of` **<mark> Loop</mark>**

Used to **iterate over iterable values** (like arrays, strings).

**Example:**

```javascript
let fruits = ["apple", "banana", "cherry"];

for (let fruit of fruits) {
  console.log(fruit);
}

/* 
apple
banana
cherry
*/
```

**<mark>6. </mark>** `break` **<mark> and </mark>** `continue`

* `break` → Exits the loop.
    
* `continue` → Skips the current iteration and moves to the next.
    

**Example (**`break`**):**

```javascript
for (let i = 1; i <= 5; i++) {
  if (i === 3) break;
  console.log(i);
}

/* 
1
2
*/
```

**Example (**`continue`**):**

```javascript
for (let i = 1; i <= 5; i++) {
  if (i === 3) continue;
  console.log(i);
}

/*
1
2
4
5
*/
```

**Loop Comparison Table**

| **Loop Type** | **Used For** | **Executes At Least Once?** |
| --- | --- | --- |
| `for` | Known number of iterations | ❌ |
| `while` | Condition-based looping | ❌ |
| `do...while` | At least one run, then condition | ✅ |
| `for...in` | Loop through object keys | ❌ |
| `for...of` | Loop through iterable values | ❌ |

---

## Array

An **array** is a special variable in JavaScript that can hold **multiple values** in a single variable.

```javascript
let fruits = ["apple", "banana", "cherry"];
```

**How to Declare an Array**

```javascript
// Using square brackets
let colors = ["red", "blue", "green"];

// Using the Array constructor
let numbers = new Array(1, 2, 3, 4);
```

**Accessing Array Elements**

Array indexing starts at `0`.

```javascript
let animals = ["dog", "cat", "rabbit"];

console.log(animals[0]); // dog
console.log(animals[2]); // rabbit
```

**Array Methods (Most Common)**

| **Method** | **Description** | **Example** |
| --- | --- | --- |
| `push()` | Add to the **end** | `arr.push("item")` |
| `pop()` | Remove from the **end** | `arr.pop()` |
| `shift()` | Remove from the **start** | `arr.shift()` |
| `unshift()` | Add to the **start** | `arr.unshift("item")` |
| `length` | Get array length | `arr.length` |
| `indexOf()` | Find index of an item | `arr.indexOf("item")` |
| `includes()` | Check if array includes item | `arr.includes("item")` |
| `slice(start, end)` | Extract a portion of array | `arr.slice(1, 3)` |
| `splice()` | Add/Remove elements | `arr.splice(2, 1, "newItem")` |
| `join()` | Join all elements into a string | `arr.join(", ")` |
| `reverse()` | Reverse the array | `arr.reverse()` |
| `sort()` | Sort elements | `arr.sort()` |

**Looping Through Arrays -**

**Using** `for` **loop:**

```javascript
let fruits = ["apple", "banana", "cherry"];

for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}
```

**Using** `for...of`**:**

```javascript
for(let fruit of fruits) {
  console.log(fruit);
}
```

**Using** `forEach()`**:**

```javascript
fruits.forEach(function(fruit) {
  console.log(fruit);
});
```

**Example**

```javascript
let scores = [10, 20, 30, 40];

// Add a score
scores.push(50);
// [ 10, 20, 30, 40, 50 ]

// Remove first score
scores.shift();
//[ 20, 30, 40, 50 ]

// Find score
console.log(scores.includes(30)); 
// true

// Sum all scores
let sum = 0;
for (let score of scores) {
  sum += score;
}
console.log("Total:", sum);
// Total: 140
```

**Nested Arrays (2D Arrays)**

```javascript
let matrix = [
  [1, 2],
  [3, 4],
  [5, 6]
];

console.log(matrix); //[ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ]
console.log(matrix[1][0]); // 3
```

> JavaScript arrays are **dynamic** and **can hold mixed data types** (but avoid that in practice).

```javascript
let mixed = [1, "hello", true, null];
```
