[Go to site: main page, start]

0% found this document useful (0 votes)
18 views270 pages

My Java Script

This document provides a comprehensive guide on setting up Visual Studio Code as an IDE for JavaScript development, including installation steps for Windows and recommended extensions. It also covers fundamental JavaScript concepts such as variables, data types, and string manipulation techniques like concatenation and template literals. The importance of good variable naming conventions and the differences between variable declaration keywords (var, let, const) are also discussed.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views270 pages

My Java Script

This document provides a comprehensive guide on setting up Visual Studio Code as an IDE for JavaScript development, including installation steps for Windows and recommended extensions. It also covers fundamental JavaScript concepts such as variables, data types, and string manipulation techniques like concatenation and template literals. The importance of good variable naming conventions and the differences between variable declaration keywords (var, let, const) are also discussed.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

JAVA SCRIPT

Setup IDE - VS Code Installation

Visual Studio Code is the most popular code editor and the IDEs provided by Microsoft for writing different
programs and languages. It allows the users to develop new code bases for their applications and allow
them to successfully optimize them and debug them properly. It is a very user-friendly code editor and it is
supported on all the different types of operating systems like Windows, macOS, and Linux. It has support for
all the languages like C, C++, Java, Python, JavaScript, React, Node JS, etc.

Installing Visual Studio Code on Windows

Follow the below steps to install Visual Studio Code on Windows:

Step 1: Visit the official website of the Visual Studio Code using any web browser like Google Chrome, Microsoft
Edge, etc.

Step 2: Press the “Download for Windows” button on the website to start the download of the Visual Studio
Code Application.

Step 3: When the download finishes, then the Visual Studio Code icon appears in the downloads folder.
Step 4: Click on the installer icon to start the installation process of the Visual Studio Code.

Step 5: After the Installer opens, it will ask you for accepting the terms and conditions of the Visual Studio Code.
Click on I accept the agreement and then click the Next button.

Step 6: Choose the location data for running the Visual Studio Code. It will then ask you for browsing the
location. Then click on Next button.
Step 7:Then it will ask for beginning the installing setup. Click on the Install button.

Step 8: After clicking on Install, it will take about 1 minute to install the Visual Studio Code on your device.

Step 9: After the Installation setup for Visual Studio Code is finished, it will show a window like this below.
Tick the “Launch Visual Studio Code” checkbox and then click Next.
Step 10: After the previous step, the Visual Studio Code window opens successfully. Now you can create a new
file in the Visual Studio Code window and choose a language of your choice to begin your programming
journey!

So this is how we successfully installed Visual Studio Code on our Windows system.

After installation, you would need to open the extensions tab and download the following extensions -

1. Code Runner ~ Jun Han (this will be used to run our JavaScript)

2. Bracket Pair Colorization Toggler ~ Dzhavat Ushev (this will colourize bracket pairs in our code)

3. Beautify ~ HookyQR

4. Prettier - Code Formatter ~ Prettier

5. Live Server ~ Ritwick Dey (Lets us serve our program on localhost)

First program - Hello Geeks


The [Link]() is a function in JavaScript that is used to print any kind of variables defined before it or to print
any message that needs to be displayed to the user.

Syntax:
[Link](" ");

Parameters: It accepts a parameter that can be an array, an object, or any message.


Return value: It outputs the value of the given parameter to the console.

If the message is passed to the function [Link](), then the function will display the given message.
[Link]("Hello Geeks");
Output
Hello Geeks

If an arithmetic calculation is passed to the [Link]() function, then it will display the result of the calculation.

[Link](7 + 3);

Output

10

Javascript Variables

Welcome back to our JavaScript journey! In this lesson, we will delve into the concept of variables, why they are
important, and how to use them effectively in JavaScript. Variables are fundamental to programming and
are essential for storing and managing data in your applications.

What is a Variable?
A variable is a named placeholder that holds data or information. In simpler terms, variables are used to store
values that can be used and manipulated throughout your code. Think of variables as containers that hold
different types of data, such as text, numbers, or even more complex structures.

Why Use Variables?

Let's consider an e-commerce application where you need to add products to a wishlist or a cart. JavaScript
needs to store the information about these products to manage them effectively. This is where variables
come into play. By storing data in variables, you can easily reference and manipulate that data later in your
code.

How to Create Variables


There are three main ways to declare variables in JavaScript: var, let, and const. Each has its own use case and
scope rules.

Declaring Variables with var

The var keyword is used to declare a variable. Here's how you can create and use a variable with var:
var message;
message = "Hello, Geeks!";
[Link](message); // Outputs: Hello, Geeks!
Output
Hello, Geeks!

In the above example, we first declare a variable named message using var. We then assign the string "Hello,
Geeks!" to it. Finally, we use [Link]() to display the value of the message variable.

Declaring Variables with let

The let keyword is a more modern way to declare variables and is generally preferred over var due to its block-
scoping feature.
let text = "JavaScript is the best!";
[Link](text); // Outputs: JavaScript is the best!

Output

JavaScript is the best!

Here, we declare a variable named text and assign it the value "JavaScript is the best!". We then log the value
of text to the console.

Declaring Variables with const

The const keyword is used to declare variables that are meant to be constants, meaning their values should not
change once assigned.

const number = 10;


[Link](number); // Outputs: 10

Output

10

With const, you must assign a value at the time of declaration, and this value cannot be changed later in your
code.
Variable Assignment and Re-assignment

Variables declared with var and let can be reassigned new values, while variables declared with const cannot.

var message = "Hello, Geeks!";


message = "Hello, GeeksforGeeks!";
[Link](message); // Outputs: Hello, GeeksforGeeks!

let text = "JavaScript is the best!";


text = "JavaScript is awesome!";
[Link](text); // Outputs: JavaScript is awesome!

const number = 10;


number = 20; // Error: Assignment to constant variable.

Output

Hello, GeeksforGeeks!
JavaScript is awesome!
Error : Assignment to constant variable

Why Use let and const over var?


 Block Scoping: let and const are block-scoped, meaning they are only accessible within the block they
are defined. var is function-scoped, which can lead to unexpected behavior.
 Re-assignment: const ensures that variables cannot be reassigned, which helps prevent accidental
changes to important values.

Example: Updating Variables

Consider a practical example where we want to log a message multiple times and update it:
let message = "Hello, Geeks!";
[Link](message); // Outputs: Hello, Geeks!
message = "Hello, GeeksforGeeks!";
[Link](message); // Outputs: Hello, GeeksforGeeks!

const year = 2024;


[Link](year); // Outputs: 2024
// year = 2025; // Error: Assignment to constant variable.
Output

Hello, Geeks!
Hello, GeeksforGeeks!
2024

In the example above, we first declare and log the message variable. We then update message and log the new
value. We also declare a const variable year and attempt to change its value, resulting in an error.

Variable Naming Convention

Naming variables is a crucial and often overlooked skill in programming. A well-named variable can reveal
whether the code was written by a beginner or an experienced developer. In real-world projects, much time
is spent modifying and extending code. This task becomes significantly easier when variable names are clear
and descriptive.

Rules for Naming Variables


Before we discuss how to come up with good variable names, let's review the rules for creating them:

1. Characters Allowed: A variable name can consist of letters (both uppercase and lowercase),
numbers, the dollar sign ($), and the underscore (_).
2. No Leading Numbers: A variable name cannot start with a number but can end with one.
3. No Special Characters: Avoid special characters such as @, #, -, or brackets.

let username;
let age;
let _isValid;
let $price;
let number1;
let number_2;
When a variable name consists of multiple words, you should not separate them with spaces. Instead, use
camelCase or underscores.

let userName; // camelCase


let user_age; // using underscore

Writing Good Variable Names


Good variable names should describe the type of data stored in them. This practice enhances code readability
and maintainability, especially in larger codebases. Here are some tips for writing good variable names:

1. Descriptive Names: The name should convey the variable's purpose or the type of data it holds.
2. Consistent Naming Convention: Follow a consistent naming convention, such as camelCase, for
easier readability.

Practical Examples

Consider the following examples to understand how naming impacts code clarity:

let userName = "Prakash";


[Link](userName); // Outputs: Prakash
The variable name userName clearly indicates that it stores a user's name. Now, imagine if we named it x instead:

let x = "Prakash";
[Link](x); // Outputs: Prakash
The variable name x does not convey any meaningful information about the data it holds. It could be anything,
making the code harder to understand.

Variable Name Conventions

1. Single Word Variables: Use descriptive names for single-word variables.

let age = 25;


2. Multiple Words Variables: Use camelCase or underscores.

let homeAddress = "123 Main St"; // camelCase


let home_address = "123 Main St"; // using underscore
3. Case Sensitivity: Remember that variable names are case-sensitive.

let userAge = 25;


let UserAge = 30; // Different variable

Avoid Unnecessary Symbols

While $ and _ are allowed, avoid using them unnecessarily, as they can make the code look cluttered and
unprofessional. Only use these symbols if they enhance the clarity of your code.

let $price = 100;


let _isValid = true;
Summary
In summary, good variable names are essential for writing clean, readable, and maintainable code. Follow these
guidelines to improve your variable naming skills:

 Use descriptive names that convey the variable's purpose.


 Follow a consistent naming convention, such as camelCase.
 Avoid starting variable names with numbers.
 Avoid unnecessary symbols like $ and _.

Data Types

JavaScript is a powerful and flexible language used for both client-side and server-side programming. One of the
key concepts in JavaScript is the use of data types. In this article, we will explore the various data types
available in JavaScript, their usage, and how to work with them.

What Are Data Types?

In programming, data types refer to the kind of value a variable can hold. In JavaScript, data types can be
broadly categorized into two groups: primitive and non-primitive data types. Understanding these data
types is essential as they determine how values are stored and manipulated in your program.

1. Strings

A string is a data type used to represent textual data. A string is any set of characters enclosed in quotes, either
single (') or double ("), or even backticks (`).
let username = "Prakash";
[Link](username); // Outputs: Prakash

Output

Prakash

If you omit the quotes, JavaScript will treat the text as a variable name, which will cause an error if the variable is
not defined.

let username = Prakash;


To determine the type of a variable, you can use the typeof operator:
[Link](typeof username);

Output

undefined

[Link]

The number data type is used to represent numeric values. In JavaScript, numbers can be integers or floating-
point (decimals).

let age = 25;


[Link](typeof age); // Outputs: number

let price = 99.99;


[Link](typeof price); // Outputs: number

Output

number
number

If you enclose numbers in quotes, they become strings.

let numberString = "123";


[Link](typeof numberString)

Output

string

3. Boolean

A Boolean data type has only two possible values: true or false. It is typically used to perform conditional checks
or represent binary states, such as whether a product is in a shopping cart or not.

let isProductInCart = true;


[Link](typeof isProductInCart); // Output: boolean
Output

boolean

A Boolean can be checked directly in a conditional statement:

if (isProductInCart) { [Link]("Product is in the cart.");} else { [Link]("Product is not in the cart.");}

If you try to use "true" or "false" in quotes, they will be treated as strings:

let isProductInCart = "true"; // treated as a [Link](typeof isProductInCart); // Output: string

[Link]

The undefined data type is used when a variable is declared but not yet assigned a value. JavaScript
automatically assigns the value undefined to such variables.
let username;
[Link](username); // Outputs: undefined
[Link](typeof username); // Outputs: undefined

Output

undefined
undefined

5. Null

The null data type is used to represent the intentional absence of any value. It is explicitly set to indicate that a variable
should have no value.

let user = null;


[Link](user); // Outputs: null
[Link](typeof user); // Outputs: object

Output

null
object

6. Objects
An object is a non-primitive data type used to store collections of data. Objects can hold multiple values as key-
value pairs. You can create an object using curly braces {}.

const person = {
name: "Prakash",
age: 25,
education: "Engineer"
};
[Link](typeof person); // Outputs: object

Output

object

7. Arrays

An array is a special type of object used to store ordered collections of values. Arrays are defined using square
brackets [].

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


[Link](typeof numbers);

Output

object

Summary of Data Types

Here are the primary data types we discussed:

1. String: Text enclosed in quotes.


2. Number: Integers or floating-point numbers.
3. Boolean: True or false values.
4. Undefined: Variables declared but not assigned a value.
5. Null: Represents "no value."
6. Object: Non-primitive type for storing collections of data.
7. Array: A special type of object for storing lists of values.

Concatenation and Template Literal


In this lesson, we will learn how to construct strings dynamically in JavaScript using string concatenation and
template literals. This is a crucial skill for creating meaningful and readable messages in your programs,
especially when the content of the message includes variable data.

String Concatenation
String concatenation is the process of joining two or more strings together using the + operator. This method has
been around since the early days of JavaScript.

Example

Suppose we have two variables, username and age, and we want to create a message that includes these
variables:

let username = "Prakash";


let age = 99;
let message = "My name is " + username + " and I am " + age + " years old.";
[Link](message);

Explanation

1. Variable Declaration: We declare and initialize the variables username and age.
2. String Concatenation: We use the + operator to concatenate the strings and variables into a
complete message.
3. Console Output: We log the message to the console.
Output
My name is Prakash and I am 99 years old.

However, string concatenation can become cumbersome and less readable, especially with longer strings and
multiple variables.

Template Literals
Template literals provide a more readable and convenient way to include variables in strings. They are enclosed
by backticks (`) and allow embedded expressions using ${}.

Example

We can achieve the same result as above using template literals:


let username = "Prakash";
let age = 99;
let message = `My name is ${username} and I am ${age} years old.`;
[Link](message);

Explanation

1. Backticks: We use backticks to define a template literal.


2. Embedded Expressions: We embed the variables username and age directly within the string using $
{}.
Output
My name is Prakash and I am 99 years old.

Advantages of Template Literals


1. Readability: Template literals improve the readability of your code by avoiding the clutter of
multiple + operators.
2. Multiline Strings: Template literals allow for multiline strings without the need for escape sequences.

Multiline Example

let username = "Prakash";


let age = 99;
let multilineMessage = `My name is ${username}.
I am ${age} years old.
I love to code, eat, and sing.`;
[Link](multilineMessage);

Output

My name is Prakash.
I am 99 years old.
I love to code, eat, and sing.

Practice Exercise
To reinforce your understanding, try creating a few sentences using both concatenation and template literals.
Here are some ideas:

1. Favorite Hobby: Create a message about your favorite hobby.


2. Favorite Cuisine: Create a message about your favorite cuisine.
3. Multiline Message: Create a multiline message about your daily routine.

Example with Favorite Hobby


let hobby = "coding";
let concatenationMessage = "My favorite hobby is " + hobby + ".";
let templateLiteralMessage = `My favorite hobby is ${hobby}.`;
[Link](concatenationMessage);
[Link](templateLiteralMessage);

Output

My favorite hobby is coding.


My favorite hobby is coding.

Example with Favorite Cuisine

let cuisine = "Italian food";


let concatenationMessage = "I love " + cuisine + ".";
let templateLiteralMessage = `I love ${cuisine}.`;
[Link](concatenationMessage);
[Link](templateLiteralMessage);

Output

I love Italian food.


I love Italian food.

Example with Multiline Message:

let hobby = "coding";


let multilineMessage = `My favorite hobby is ${hobby}.
I spend a lot of time practicing ${hobby}.
It's very rewarding.`;
[Link](multilineMessage);

Output

My favorite hobby is coding.


I spend a lot of time practicing coding.
It's very rewarding.

Arithmetic Operators - JS
Mathematical operations in JavaScript are similar to those in other programming languages. However, JavaScript
behaves differently when applying mathematical operators to strings. Let's dive into these operations and
understand their nuances.

Basic Mathematical Operations


We can perform basic arithmetic operations such as addition, subtraction, multiplication, division, finding
remainders, and exponentiation.

Example

Let's start with two variables:

const x = 12;
const y = 3;

//Addition:
[Link](x + y); // Outputs: 15

//Subtraction:
[Link](x - y); // Outputs: 9

//Multiplication:
[Link](x * y); // Outputs: 36

//Division:
[Link](x / y); // Outputs: 4

Remainder:
[Link](x % y); // Outputs: 0

//Exponentiation:
[Link](x ** 2); // Outputs: 144
[Link](y ** 3); // Outputs: 27

Output

15
9
36
4
0
144
27

Understanding Operators

 +: Addition operator
 -: Subtraction operator
 *: Multiplication operator
 /: Division operator
 %: Remainder (modulus) operator
 **: Exponentiation operator

Type Conversion with Operators


JavaScript automatically handles type conversion in many cases. Let's see how it behaves when using different
types.

Adding Strings and Numbers

When adding a string and a number, JavaScript treats the number as a string and concatenates them.

const x = "12";
const y = "3";
[Link](x + y); // Outputs: "123"

Output

123

Other Operations with Strings and Numbers

For subtraction, multiplication, and division, JavaScript converts strings to numbers if possible.

[Link](x - y); // Outputs: 9


[Link](x * y); // Outputs: 36
[Link](x / y); // Outputs: 4

Mixing Types

When one operand is a number and the other is a string:


const x = 12;
const y = "3";
[Link](x + y); // Outputs: "123"
[Link](x - y); // Outputs: 9
[Link](x * y); // Outputs: 36
[Link](x / y); // Outputs: 4

Output

123
9
36
4

Handling Non-Numeric Strings

If the string cannot be converted to a number, JavaScript returns NaN (Not-a-Number).

const x = "apple";
const y = "mango";
[Link](x + y); // Outputs: "applemango"
[Link](x - y); // Outputs: NaN
[Link](x * y); // Outputs: NaN
[Link](x / y); // Outputs: NaN

Output

applemango
NaN
NaN
NaN

Best Practices
When dealing with user input or any data that might be in string format, it's essential to convert strings to
numbers explicitly to avoid unexpected results.

Example

Suppose you are taking input from a user and want to perform arithmetic operations:
const userInput = "42"; // Simulating user input
const numberInput = Number(userInput);

if (!isNaN(numberInput)) {
[Link](numberInput + 8); // Outputs: 50
} else {
[Link]('Invalid input');
}

Output

50

Type conversion

Type conversion is an essential concept in JavaScript that allows us to convert one data type into another. This is
particularly useful in situations where data from an HTML input or text area needs to be manipulated as a
different type, such as converting a string to a number.

Why Use Type Conversion?


Consider an HTML text area that always provides data as a string. If the user enters a number, you might need
this number to be treated as a numeric value for calculations. This is where type conversion comes in handy.

Converting Strings to Numbers


Let's start with an example of converting strings to numbers. Suppose you have two variables storing numbers as
strings:

const a = "3";const b = "10";

If you try to add these strings directly, JavaScript will concatenate them, resulting in "310" instead of the
numeric sum 13.

[Link](a + b); // Outputs: 310

To achieve the desired numeric addition, you need to convert these strings to numbers using
the Number function:

const aNumber = Number(a);const bNumber = Number(b);[Link](aNumber + bNumber); // Outputs: 13

Example with Type Checking


Let's see how this works in practice with type checking:

const a = "3";
const b = "10";
const c = Number(a);
const d = Number(b);

[Link](typeof a); // Outputs: string


[Link](typeof b); // Outputs: string
[Link](typeof c); // Outputs: number
[Link](typeof d); // Outputs: number

Output

string
string
number
number

Initially, a and b are strings. After conversion, c and d become numbers.

Converting Numbers to Strings


You might also need to convert numbers back to strings. This can be done using the String function:

const num = 123;


const str = String(num);
[Link](typeof str); // Outputs: string

Output

string

Example with Type Checking

Here's an example of converting numbers to strings and checking their types:

const num1 = 123;


const num2 = 456.78;
const str1 = String(num1);
const str2 = String(num2);
[Link](typeof num1); // Outputs: number
[Link](typeof num2); // Outputs: number
[Link](typeof str1); // Outputs: string
[Link](typeof str2); // Outputs: string

Output

number
number
string
string

Initially, num1 and num2 are numbers. After conversion, str1 and str2 are strings.

Converting to Boolean
Boolean conversion is another useful type conversion. This is done using the Boolean function, which converts
values to true or false.

Conversion Rules

 Any non-empty string is true.


 An empty string is false.
 The number 0 is false.
 Any other number is true.

Example with Strings

const str1 = "Hello";


const str2 = "";

[Link](Boolean(str1)); // Outputs: true


[Link](Boolean(str2)); // Outputs: false

Output

true
false

Example with Numbers


const num1 = 10;
const num2 = 0;

[Link](Boolean(num1)); // Outputs: true


[Link](Boolean(num2)); // Outputs: false

Example with Type Checking

const str = "Hello";


const num = 0;

[Link](Boolean(str)); // Outputs: true


[Link](Boolean(num)); // Outputs: false

Output

true
false

Practical Examples
Example 1: Converting User Input from Text Area

Consider a scenario where you get user input from a text area and need to perform arithmetic operations:

const input = "42"; // User input as a string


const number = Number(input);

if (!isNaN(number)) {
[Link](number + 8); // Outputs: 50
} else {
[Link]("Invalid input");
}

Output

50

Example 2: Checking Boolean Values

Let's check Boolean values for various data types:


[Link](Boolean("Prakash")); // Outputs: true
[Link](Boolean("")); // Outputs: false
[Link](Boolean(0)); // Outputs: false
[Link](Boolean(100)); // Outputs: true
[Link](Boolean(-1)); // Outputs: true

Output

true
false
false
true
true

ReadlineSync

In this Article, we will continue exploring type conversion in JavaScript, focusing on real-life scenarios such as
extracting and converting user input. Type conversion is essential when dealing with different data types,
especially when you need to manipulate user-provided data from input fields.

Why Type Conversion is Important


When taking data from an input field, it is usually in the form of a string, even if the user enters a number. To
perform numeric operations, you need to convert these strings to numbers. Let's see how we can do this in
JavaScript.

Installing Necessary Packages


Before we dive into the code, we need to set up our environment. Ensure you have [Link] installed on your
system. [Link] comes with npm (Node Package Manager), which we will use to install packages.

1. Install [Link]: Download and install [Link] from the official website.
2. Install readline-sync Package: This package allows us to read user input from the terminal.
Open your terminal and run the following command to install readline-sync:
npm install readline-sync

Getting User Input


Let's create a simple script to get data from the user and convert it to the appropriate data type.

1. Set Up readline-sync:
const readlineSync = require('readline-sync');
2. Ask for User Input:

const userName = [Link]('May I know your name? ');


[Link](`Welcome, ${userName}!`);
3. Convert and Use Numeric Input:

Let's extend this to ask the user for their age and calculate their birth year.

const userAge = [Link]('May I know your age? ');

// Convert the input to a number


const userAgeNumber = Number(userAge);

// Check if the conversion was successful


if (!isNaN(userAgeNumber)) {
const currentYear = new Date().getFullYear();
const birthYear = currentYear - userAgeNumber;
[Link](`You were born in the year ${birthYear}.`);
} else {
[Link]('Please enter a valid number for age.');
}

Detailed Explanation

 Asking for Input: We use [Link]() to prompt the user and capture their input.
 Converting String to Number: The Number() function converts the string input to a number. If the
input is not a valid number, it returns NaN (Not-a-Number).
 Checking the Conversion: We use isNaN() to check if the conversion was successful.

Example with Full Code

Here's the complete code for a better understanding:

const readlineSync = require('readline-sync');

// Get user's name


const userName = [Link]('May I know your name? ');
[Link](`Welcome, ${userName}!`);

// Get user's age


const userAge = [Link]('May I know your age? ');
// Convert the input to a number
const userAgeNumber = Number(userAge);

// Check if the conversion was successful


if (!isNaN(userAgeNumber)) {
const currentYear = new Date().getFullYear();
const birthYear = currentYear - userAgeNumber;
[Link](`You were born in the year ${birthYear}.`);
} else {
[Link]('Please enter a valid number for age.');
}

Running the Code

To run this code, open your terminal, navigate to the directory containing your script, and use the following
command:
node [Link]

Replace [Link] with the name of your JavaScript file.

Key Points

1. Type Conversion: Converting data from one type to another is essential for performing various
operations.
2. User Input: Using readline-sync to read user input from the terminal.
3. Error Handling: Checking the validity of user input and handling errors appropriately.

JavaScript Comparison Operators

In JavaScript, comparison operators are used to compare two values, returning a Boolean value ( true or false).
These operators are fundamental in conditional statements, loops, and logical expressions. Understanding
how they work, including some of JavaScript's unique behavior and quirks, can help you avoid common
mistakes and unexpected results in your code.

1. Basic Comparison Operators

Basic comparison operators compare two values and return a Boolean based on the condition being met. The
following are the basic comparison operators in JavaScript:

 Greater Than (>)


 Less Than (<)
 Greater Than or Equal (>=)
 Less Than or Equal (<=)
Code Example:

[Link](50 > 30); // true


[Link](50 < 30); // false
[Link](30 >= 30); // true
[Link](50 <= 40); //false
[Link](50 == 40); // false

Output

true
false
true
false
false

Explanation:

 50 > 30 is true because 50 is indeed greater than 30.


 50 < 30 is false because 50 is not less than 30.
 30 >= 30 is true because 30 is equal to 30.
50 <= 40 is false because 50 is not less than equal to 40.

50 == 40 is false because 50 is not equal to 40.

These operators are straightforward, but their use can become tricky in certain cases (like string comparisons or
type coercion, which we will discuss later).

2. Comparison of Strings

In JavaScript, strings are compared based on their ASCII (Unicode) values. When comparing two strings,
JavaScript checks their characters from left to right, comparing the ASCII values of each character.

Code Example:

[Link]("apple" > "banana"); // false


[Link]("glowing" > "glow"); // true

Output

false
true
Explanation:

 "apple" > "banana" returns false because 'a' (ASCII: 97) is less than 'b' (ASCII: 98).
 "glowing" > "glow" returns true because after comparing the common characters ('g', 'l', 'o', 'w'), the
string "glowing" has additional characters.
This comparison is case-sensitive, meaning uppercase letters have a lower ASCII value than lowercase letters,
which affects string comparisons.

3. Type Coercion in Comparison

JavaScript performs type coercion in certain comparisons, meaning it automatically converts one data type to
another. This can lead to unexpected results, especially when comparing strings and numbers.

Code Example:

[Link]("2" > 1); // true


[Link]("01" == 1); // true

Explanation:

 "2" > 1 is true because the string "2" is converted to the number 2, and 2 > 1 is true.
 "01" == 1 is true because the string "01" is converted to the number 1, and 1 == 1 is true.
To avoid such unexpected behavior, it's best to use strict equality ( ===), which we will cover next.

4. Strict Equality (===) vs. Loose Equality (==)

Loose Equality (==): Converts the values before comparing them.



Strict Equality (===): Checks both the value and the type.

Code Example:

[Link]("01" === 1); // false

Output

false

Explanation:

 "01" === 1 is false because "01" is a string, while 1 is a number. The strict equality operator ( ===) does
not perform type conversion, so it returns false.
In general, it’s advisable to use strict equality (===) to prevent unintentional type coercion that can lead to bugs.

5. Null and Undefined in Comparison

JavaScript has special rules when comparing null and undefined. While they are loosely equal (==), they are not
strictly equal (===).

Code Example:

[Link](null == undefined); // true


[Link](null === undefined); // false

Output

true
false

Explanation:

 null == undefined is true because JavaScript considers them loosely equal in value.
 null === undefined is false because their types are different ( null is an object, and undefined is a type
itself).

6. Null in Mathematical Comparisons

null has unique behavior when used in mathematical comparisons (such as <, >, <=, >=). In these
comparisons, null is treated as 0.

Code Example:

[Link](null > 0); // false


[Link](null < 1); // true
[Link](null >= 0); // true
[Link](null == 0); // false

Output

false
true
true
false

Explanation:

 null > 0 is false because null is treated as 0, and 0 > 0 is false.


 null < 1 is true because null is treated as 0, and 0 < 1 is true.
 null >= 0 is true because null is treated as 0, and 0 >= 0 is true.
 null == 0 is false because null is not converted to 0 in equality checks (==).

7. Examples and Exercises

Let's put some of these comparisons to the test! Try predicting the output of the following comparisons.

Code Example:

[Link](3 <= 5); // true


[Link]("mango" > "banana"); // true
[Link]("2" > "3"); // false
[Link](undefined == null); // true
[Link](null === undefined); // false
[Link](null < 1); // true

Output

true
true
false
true
false
true

Key Takeaways
 Always use === instead of == to avoid issues with type coercion.
 String comparisons are done based on ASCII (Unicode) values.
 JavaScript automatically converts strings to numbers in numerical comparisons.
 Null behaves differently in mathematical and equality comparisons.
 Undefined always results in false in numerical comparisons.

JavaScript Conditional Statements


In this article, we will explore conditional statements in JavaScript, focusing on how they work, their syntax, and
practical use cases. We'll cover different ways to use conditions to manipulate outputs based on certain
criteria. Conditional statements help control the flow of code, allowing it to make decisions based on
conditions.

What Are Conditional Statements?

A conditional statement allows the program to execute certain code based on a condition being true or false.
For example, when building an e-commerce application, you might want to display the user's cart only if
they are logged in. If the user is not logged in, you can show a login prompt instead of displaying the cart.

Conditional statements are a crucial part of any application, and in JavaScript, they are written using keywords
like if, else, and else if.

The if Statement

The if statement evaluates a condition, and if the condition is true, it executes the code inside the curly braces {}.
If the condition is false, it does nothing unless paired with an else or else if statement.

Syntax of an if statement:
if (condition) {
// Code to be executed if the condition is true
}

Flow chart:
Here’s a simple example that checks if a user is logged in:

const isLoggedIn = true;

if (isLoggedIn) {
[Link]("You are logged in.");
}

Output

You are logged in.

In this example, the condition isLoggedIn is true, so the message "You are logged in." is printed.

Explanation:
 The condition isLoggedIn evaluates to a boolean value.
 If the condition is true, the code inside the curly braces is executed.
 If the condition is false, the code is skipped.
Using Comparison Operators in Conditions

In many cases, conditions involve comparison operators. For example, checking if a user's age is greater than 18
can be done using the > operator.

Example:

const userAge = 18;

if (userAge > 16) {


[Link]("You are an adult.");
} else {
[Link]("You are a minor.");
}

Output

You are an adult.

The else Statement

An else statement is used to run a block of code when the condition in the if statement evaluates to false.

Syntax:
if (condition) {
// Code to be executed if the condition is true
} else {
// Code to be executed if the condition is false
}

Flow chart:
Example:

const userAge = 15;

if (userAge > 16) {


[Link]("You are an adult.");
} else {
[Link]("You are not an adult.");
}

Output

You are not an adult.

The else if Statement

In case you need to check multiple conditions, you can use the else if statement. This allows you to check
additional conditions if the first if condition fails.
Syntax:
if (condition1) {
// Code to be executed if condition1 is true
} else if (condition2) {
// Code to be executed if condition2 is true
} else {
// Code to be executed if none of the above conditions are true
}

Example:

const userAge = 30;

if (userAge < 18) {


[Link]("You are a minor.");
} else if (userAge >= 18 && userAge < 60) {
[Link]("You are an adult.");
} else {
[Link]("You are a senior.");
}

Output

You are an adult.

Using Logical Operators


JavaScript supports logical operators like AND (&&), OR (||), and how to combine multiple conditions in
JavaScript. We’ll also dive into using the readline-sync module to handle user input for checking conditions
dynamically. Let's break down each concept with code examples and explanations.

The AND Operator (&&)

The AND operator (&&) is used when you want to check if both conditions are true. If both conditions are true,
the entire expression evaluates to true.

Example:

const readlineSync = require("readline-sync");

const number = Number([Link]("Enter a number: "));


const remainderAfterDivisionByThree = number % 3;
const remainderAfterDivisionByFive = number % 5;

if (remainderAfterDivisionByThree === 0 && remainderAfterDivisionByFive === 0) {


[Link]("Fizz");
} else {
[Link]("The number is not divisible by both 3 and 5.");
}

Explanation:

 The code checks if the entered number is divisible by both 3 and 5.


 If the remainder of dividing the number by 3 and 5 is zero, it prints "Fizz."
 Otherwise, it prints "The number is not divisible by both 3 and 5."
Output:
Enter a number: 15
Fizz

The OR Operator (||)

The OR operator (||) is used when you want to check if either of the conditions is true. If at least one condition
is true, the expression evaluates to true.

Example:

const readlineSync = require("readline-sync");

const number = Number([Link]("Enter a number: "));


const remainderAfterDivisionByThree = number % 3;
const remainderAfterDivisionByFive = number % 5;

if (remainderAfterDivisionByThree === 0 || remainderAfterDivisionByFive === 0) {


[Link]("Buzz");
} else {
[Link]("The number is not divisible by 3 or 5.");
}

Explanation:

 The code checks if the number is divisible by 3 or 5.


 If either condition is true, it prints "Buzz."
 If neither condition is true, it prints "The number is not divisible by 3 or 5."
Output:
Enter a number: 10
Buzz
Combining Multiple Conditions

You can combine multiple conditions using AND (&&) and OR (||) to create more complex decision-making
scenarios. For example, you can check if a number is divisible by both 3 and 5 and then perform actions
accordingly.

Example:

const readlineSync = require("readline-sync");

const number = Number([Link]("Enter a number: "));


const remainderAfterDivisionByThree = number % 3;
const remainderAfterDivisionByFive = number % 5;
const remainderAfterDivisionBySeven = number % 7;

if (remainderAfterDivisionByThree === 0 && remainderAfterDivisionByFive === 0) {


[Link]("Fizz");
} else {
[Link]("Not divisible by both 3 and 5.");
}

if (remainderAfterDivisionByThree === 0 || remainderAfterDivisionByFive === 0) {


[Link]("Buzz");
} else {
[Link]("Not divisible by 3 or 5.");
}

if (remainderAfterDivisionBySeven === 0) {
[Link]("BuzzBuzz");
} else {
[Link]("Not divisible by 3, 5, and 7");
}

Explanation:

The first condition checks if the number is divisible by both 3 and 5, and if so, it prints "Fizz."
The second condition checks if the number is divisible by 3 or 5, and if so, it prints "Buzz."
The third condition checks if the number is divisible by 7, and if so, it prints "BuzzBuzz."
Output Example:
Enter a number: 30
Fizz
Buzz
BuzzBuzz

In this case, since 30 is divisible by 3, 5, and 7, all conditions are satisfied, and corresponding messages are
printed.

Using the readline-sync Module


The readline-sync module is used to handle user input in a more interactive way, allowing the user to enter values
dynamically. This is especially useful in command-line applications or interactive scripts.

In our previous examples, we used [Link]() to prompt the user to enter a number. This way, the
program doesn't rely on hardcoded values but can take input during execution.

Example Using readline-sync:

const readlineSync = require("readline-sync");

const number = Number([Link]("Enter a number: "));


const remainderAfterDivisionByThree = number % 3;
const remainderAfterDivisionByFive = number % 5;
const remainderAfterDivisionBySeven = number % 7;

if (remainderAfterDivisionByThree === 0 && remainderAfterDivisionByFive === 0) {


[Link]("Fizz");
} else if (remainderAfterDivisionByThree === 0 || remainderAfterDivisionByFive === 0) {
[Link]("Buzz");
} else if (remainderAfterDivisionBySeven === 0) {
[Link]("BuzzBuzz");
} else {
[Link]("Not divisible by 3, 5, or 7.");
}

In this case, the program will ask the user to input a number, and based on that input, it will check the conditions
and display the appropriate message.

Summary of Key Points

1. if statements evaluate conditions and execute code if the condition is true.


2. else statements execute code if the if condition is false.
3. else if allows you to check additional conditions if the initial condition is false.
4. Use logical operators like && (AND) and || (OR) to combine multiple conditions.
5. Use the modulus operator to check divisibility conditions.
Conditional statements are an essential part of any programming language, enabling the control flow of
applications. By combining if, else, and else if, as well as using logical operators, you can create flexible and
complex decision-making structures in your code.

JavaScript Ternary Operator


Ternary operators offer a compact way to write conditional expressions in JavaScript. They can be used as a
shorthand for if-else statements, making your code more concise and readable. In this lesson, we'll explore
how to use ternary operators and compare them to traditional if-else statements.

Understanding Ternary Operators


A ternary operator is a one-liner shorthand for if-else statements. It uses the syntax:

condition ? expressionIfTrue : expressionIfFalse


 Condition: A statement that returns true or false.
 Value if True: What happens if the condition is true?
 Value if False: What happens if the condition is false?
Let's start by converting a simple if-else condition into a ternary operator.

Example: Traditional if-else Statement

Consider the following if-else statement:

const totalMarks = 60;

if (totalMarks < 40) {


[Link]("You need to work hard.");
} else {
[Link]("You cleared the exam.");
}

Output

You cleared the exam.

This code checks if the totalMarks are less than 40. If true, it prints "You need to work hard." Otherwise, it prints
"You cleared the exam."

Converting to a Ternary Operator

The same logic can be written using a ternary operator:

const totalMarks = 60;

[Link](totalMarks < 40 ? "You need to work hard." : "You cleared the exam.");
Output

You cleared the exam.

Here, the condition totalMarks < 40 is followed by a question mark ( ?). The expression after the question mark
("You need to work hard.") is executed if the condition is true. The expression after the colon ( :) is executed if
the condition is false.

Assigning Result to a Variable

You can also assign the result of a ternary operator to a variable:

const totalMarks = 80;

const result = totalMarks < 40 ? "You need to work hard." : "You cleared the exam.";
[Link](result);

Output

You cleared the exam.

This way, the appropriate message is assigned to the variable result, which is then printed to the console.

Nested Ternary Operators

You can also use nested ternary operators, but be cautious as it can make the code harder to read:

const score = 85;

const grade = score > 90 ? 'A' :


score > 80 ? 'B' :
score > 70 ? 'C' :
score > 60 ? 'D' : 'F';

[Link](`Your grade is: ${grade}`);

Output

Your grade is: B

In this example, the ternary operators are nested to determine the grade based on the score.

Example: Using Ternary Operators to Replace if-else Statements


Consider a scenario where we grade a student's performance based on their total marks. Here's how we
typically write it using if-else statements:

const totalMarks = 60;

if (totalMarks < 40) {


[Link]("You need to work hard.");
} else if (totalMarks < 60) {
[Link]("B grade");
} else if (totalMarks < 75) {
[Link]("A grade");
} else if (totalMarks < 85) {
[Link]("A+ grade");
} else {
[Link]("Genius");
}

Output

A grade

Converting to Ternary Operators

We can achieve the same logic using a single line of code with ternary operators:

const totalMarks = 60;

const result = totalMarks < 40 ? "You need to work hard." :


totalMarks < 60 ? "B grade" :
totalMarks < 75 ? "A grade" :
totalMarks < 85 ? "A+ grade" : "Genius";

[Link](result);

Output

A grade

Here, we use nested ternary operators to handle multiple conditions. Each ternary operator checks a condition,
and if the condition is true, it returns the corresponding expression. If the condition is false, it proceeds to
the next ternary operator.

Advantages of Ternary Operators

1. Conciseness: Ternary operators make the code shorter.


2. Readability: For simple conditions, ternary operators can make the code easier to read.
3. Single-line expressions: Ternary operators are useful for inline assignments.

Drawbacks of Ternary Operators

1. Complexity: For multiple or nested conditions, ternary operators can become hard to read and
maintain.
2. Debugging: Debugging nested ternary operators can be more challenging compared to if-
else statements.

Conclusion
Ternary operators provide a powerful way to write concise conditional expressions in JavaScript. They are
particularly useful for simple conditions and inline assignments. However, for complex logic, traditional if-
else statements may be more readable and maintainable.

Practice using ternary operators to get comfortable with their syntax and usage. In future lessons, we'll explore
more advanced use cases and scenarios where ternary operators can simplify your code.

Logical Operators Part 1

Logical operators in JavaScript are used to combine multiple conditions and return a Boolean value based on the
evaluation of those conditions. There are four main logical operators:

1. AND (&&)
2. OR (||)
3. NOT (!)
4. Nullish Coalescing (??)
Let's explore these operators with examples.

AND (&&) Operator


The AND operator returns true if all the conditions are true; otherwise, it returns false.

Example:

We have scores in Physics, Chemistry, and Mathematics, and we want to check if a student is eligible for
engineering based on their scores.

const physics = 90;


const maths = 95;
const chemistry = 88;
const biology = 96;

if (physics > 85 && maths > 85 && chemistry > 85) {


[Link]("You are eligible for engineering.");
} else {
[Link]("You are not eligible for engineering.");
}

Output

You are eligible for engineering.

In this example, the message "You are eligible for engineering." will be printed because all the scores are greater
than 85.

OR (||) Operator
The OR operator returns true if at least one of the conditions is true; otherwise, it returns false.

Example:

We check if a student is eligible for engineering if at least one of the scores is greater than a specified value.

const physics = 90;


const maths = 95;
const chemistry = 88;
const biology = 96;
if (physics > 90 || maths > 85 || chemistry > 89) {
[Link]("You are eligible for engineering.");
} else {
[Link]("You are not eligible for engineering.");
}

Output

You are eligible for engineering.

In this example, the message "You are eligible for engineering." will be printed because the math score is greater
than 85.

NOT (!) Operator


The NOT operator reverses the Boolean value of the operand. If the operand is true, it returns false, and if the
operand is false, it returns true.

Example:
const isStudentEligible = false;

if (!isStudentEligible) {
[Link]("You are not eligible.");
} else {
[Link]("You are eligible.");
}

Output

You are not eligible.

In this example, the message "You are not eligible." will be printed because the isStudentEligible variable is false,
and the NOT operator reverses it to true.

JavaScript Nullish Coalescing

In JavaScript, nullish coalescing is a new type of logical operator that was introduced to help simplify
handling undefined and null values. This operator can help prevent pitfalls that might occur when working
with values like undefined, null, 0, or an empty string.

Let’s understand how this operator works and how it differs from the traditional OR ( ||) operator.

What is Nullish Coalescing (??)?

The nullish coalescing operator (??) is used to assign a default value to a variable when the value is
either null or undefined. This is particularly useful when you want to provide a fallback value only
for null or undefined, but you want to keep values like 0 or an empty string ("") intact.

The syntax for the nullish coalescing operator is:


let result = value ?? defaultValue;

In this expression:

 If value is neither null nor undefined, it will return value.


 If value is null or undefined, it will return defaultValue.

Basic Example of Nullish Coalescing:

const firstName = "Prakash";


[Link](firstName ?? "Hidden Geek"); // Output: "Prakash"
In this example, since firstName is not null or undefined, the output is "Prakash". If firstName was null or undefined,
the output would have been "Hidden Geek".

Now, let’s test how it works when firstName is undefined:

let firstName; // `firstName` is undefined


[Link](firstName ?? "Hidden Geek"); // Output: "Hidden Geek"

Here, firstName is undefined, so the nullish coalescing operator assigns the default value "Hidden Geek".

Case of Empty String:


Nullish coalescing does not treat an empty string ("") as a falsy value. This is different from the OR ( ||) operator,
which would consider an empty string as falsy.

let firstName = "";


[Link](firstName ?? "Hidden Geek"); // Output: ""

In this case, the empty string is not null or undefined, so the output remains as an empty string. If we used the OR
operator (||), it would return "Hidden Geek" since the empty string is considered falsy by OR.

Difference Between ?? and ||

Let’s now compare nullish coalescing (??) with the OR (||) operator.

OR (||) Operator:
The OR operator returns the first truthy value in an expression. It will treat values like 0, "" (empty string), null,
and undefined as falsy values.

let firstName = "";


[Link](firstName || "Hidden Geek"); // Output: "Hidden Geek"

In this case, OR considers the empty string as falsy, so it returns the fallback value "Hidden Geek".

Nullish Coalescing (??) Operator:


The nullish coalescing operator will only return the fallback value if the variable is null or undefined. It
will not return the fallback value for falsy values like 0 or "".

let firstName = "";


[Link](firstName ?? "Hidden Geek"); // Output: ""

Here, since firstName is an empty string (""), the nullish coalescing operator does not return "Hidden Geek",
because the value is neither null nor undefined.

Handling Falsy Values: The Pitfall of OR Operator

A common issue with the OR operator (||) is that it considers zero (0), empty string (""), and null/undefined as
falsy values, which might not always be the desired behavior. Let's look at an example where we want to
keep 0 as a valid value:

const a = 0;
[Link](a || 1); // Output: 1

Here, since a is 0 (which is a falsy value), the OR operator will return 1. However, 0 might be a valid value that we
want to preserve.

Now, using nullish coalescing solves this problem:

let a = 0;
[Link](a ?? 1); // Output: 0

In this case, the nullish coalescing operator correctly keeps the value 0, as 0 is not null or undefined.

Handling Undefined with Default Values

The nullish coalescing operator is especially useful when you need to assign default values to variables that may
be null or undefined, but you want to treat other falsy values (like 0 or "") as valid.

let a = 12;
let b;

[Link](a + (b ?? 0)); // Output: 12


Explanation:

 In this case, b is undefined. The nullish coalescing operator replaces it with 0, so the output is 12.

Summary of Key Differences Between || and ??:

 || (OR operator) treats all falsy values (false, 0, "", null, undefined, etc.) as false.
 ?? (Nullish Coalescing operator) only considers null and undefined as "nullish" values, and treats other
falsy values (0, "", false) as valid.

JavaScript Loops

Loops are fundamental constructs in programming that allow us to execute a block of code repeatedly.
JavaScript provides several types of loops, each with its unique use cases and syntax. In this article, we will
explore the most commonly used loops: the for loop, while loop, and do while loop. By the end of this
article, you will have a solid understanding of how to use these loops effectively in your JavaScript code.

For Loop
The for loop is one of the most commonly used loops in JavaScript. It provides a concise way to iterate over a
range of values and is often preferred over the while loop due to its compact syntax.

Syntax

The syntax of a for loop is as follows:

for (initialization; condition; increment) {

// Code to be executed in each iteration

}
 Initialization: This statement is executed once before the loop starts. It typically initializes a counter
variable.
 Condition: This expression is evaluated before each iteration. If the condition is true, the loop
continues; if false, the loop stops.
 Increment: This statement is executed after each iteration. It usually increments the counter
variable.

Example: Printing "Hello" 10 Times

var i;
for (i = 0; i < 10; i++)
{
[Link]("Hello World!");
}

Output

Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!

In this example:

 We initialize i to 0.
 The loop runs as long as i is less than 10.
 After each iteration, i is incremented by 1.
This loop prints "Hello" ten times.

Detailed Explanation

Let's break down the loop step by step:

1. Initialization: let i = 0 sets the starting value of i.


2. Condition: i < 10 is checked. If true, the loop continues.
3. Code Execution: [Link]("Hello") is executed.
4. Increment: i++ increases i by 1.
5. Steps 2-4 are repeated until the condition i < 10 is false.

While Loop

A while loop is a control flow statement that allows code to be executed repeatedly based on a given Boolean
condition. The while loop can be thought of as a repeating if statement.

Syntax :
while (boolean condition)
{
loop statements...
}

Flowchart:
flowch
art for while loop

1. While loop starts with checking the condition. If it is evaluated to be true, then the loop body
statements are executed otherwise first statement following the loop is executed. For this reason, it
is also called the Entry control loop
2. Once the condition is evaluated to be true, the statements in the loop body are executed. Normally
the statements contain an update value for the variable being processed for the next iteration.
3. When the condition becomes false, the loop terminates which marks the end of its life cycle.

Example:

var i=1;
while(i <= 10)
{
[Link]("Hello World!");
i++;
}

Output

Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!

Do While Loop

The do while loop is similar to the while loop, but it guarantees that the code inside the loop is executed at least
once, even if the condition is false.

Syntax

The syntax of a do while loop is as follows:


do {
// Code to be executed in each iteration
} while (condition);

1. Initialization condition: Here, we initialize the variable in use. It marks the start of a for loop. An
already declared variable can be used or a variable can be declared, local to loop only.
2. Testing Condition: It is used for testing the exit condition for a loop. It must return a boolean value. It
is also an Entry Control Loop as the condition is checked prior to the execution of the loop
statements.
3. Statement execution: Once the condition is evaluated to be true, the statements in the loop body
are executed.
4. Increment/ Decrement: It is used for updating the variable for the next iteration.
5. Loop termination: When the condition becomes false, the loop terminates marking the end of its life
cycle.
Example:

var i;
for (i = 0; i < 10; i++)
{
[Link]("Hello World!");
}

Output

Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!

Do-While Loop

Do-While loop is similar to the while loop with the only difference that it checks for the condition after executing
the statements, and therefore is an example of an Exit Control Loop.

Syntax:
do
{
statements..
}
while (condition);

flowchart for do-while loop

Example: Printing Numbers from 0 to 9

let i = 0;

do {
[Link](i);
i++;
} while (i < 10);

Output

0
1
2
3
4
5
6
7
8
9

In this example:

 We initialize i to 0.
 The code inside the loop is executed once before the condition is checked.
 The loop runs as long as i is less than 10.

Key Difference

The key difference between the while loop and the do while loop is that the do while loop will execute the code
inside the loop at least once, even if the condition is initially false.

Practical Example: Printing Characters of a String


Let's apply what we've learned to print each character of a string on a new line:

const name = "Prakash Sarkari";

for (let i = 0; i < [Link]; i++) {


[Link](name[i]);
}
In this example, we use a for loop to iterate over each character in the string and print it. This is a common task
in many programming scenarios.

1. The do-while loop starts with the execution of the statement(s). There is no checking of any
condition for the first time.
2. After the execution of the statements, and update of the variable value, the condition is checked for
a true or false value. If it is evaluated to be true, the next iteration of the loop starts.
3. When the condition becomes false, the loop terminates which marks the end of its life cycle.
4. It is important to note that the do-while loop will execute its statements at least once before any
condition is checked, and therefore is an example of the exit control loop.

Conclusion
Loops are powerful constructs in JavaScript that allow us to automate repetitive tasks efficiently. The for loop,
while loop, and do while loop each have their unique advantages and use cases. Understanding how to use
these loops effectively will help you write cleaner, more efficient code.
Function Declaration and use in JavaScript

Introduction

Functions are fundamental building blocks in JavaScript and any programming language. They allow you to write
reusable code, which can be executed whenever needed. This reduces redundancy and improves code
organization. In this lesson, we will dive into the concept of functions, how they work, and how to use them
effectively.

What are Functions?


A function is a block of code designed to perform a particular task. You can think of functions as a way to
encapsulate code that you might want to reuse multiple times throughout your program. Instead of writing
the same code repeatedly, you can call the function whenever you need it.

Basic Function Syntax

The basic syntax of a function includes:

1. The function keyword.


2. A name for the function.
3. Parentheses () which can contain parameters.
4. Curly braces {} that enclose the function body.

function greetMessage() {
[Link]("Hello from GeeksforGeeks!");
}

Output

Calling a Function

To execute the code inside a function, you need to call the function by its name followed by parentheses.

greetMessage(); // Output: Hello from GeeksforGeeks!

Function Declaration

The above example demonstrates a function declaration. Here, we declare a function named greetMessage and
then call it.
Function Parameters and Arguments

Functions can accept inputs, known as parameters. When you call a function, you provide values for these
parameters, known as arguments.

function greetUser(name) {
[Link](`Hello, ${name}! Welcome to GeeksforGeeks.`);
}

greetUser("Prakash"); // Output: Hello, Prakash! Welcome to GeeksforGeeks.

Output

Hello, Prakash! Welcome to GeeksforGeeks.

In this example, name is a parameter, and "Prakash" is an argument.

Multiple Parameters

A function can accept multiple parameters separated by commas.

function greetUser(name, city) {


[Link](`Hello, ${name}! Welcome to GeeksforGeeks. Thank you for joining from ${city}.`);
}

greetUser("Prakash", "Mumbai"); // Output: Hello, Prakash! Welcome to GeeksforGeeks. Thank you for joining from Mumbai.

Output

Hello, Prakash! Welcome to GeeksforGeeks. Thank you for joining from Mumbai.

Handling Missing Arguments

If you call a function without passing all the required arguments, the missing arguments will be undefined.

greetUser("Prakash"); // Output: Hello, Prakash! Welcome to GeeksforGeeks. Thank you for


joining from undefined.

Practical Example: Sum of Numbers


Let's create a function that calculates the sum of numbers within a specified range.

Exercise
Create a function calculateSum that accepts two parameters min and max, and returns the sum of all numbers
from min to max.

function calculateSum(min, max) {


let sum = 0;
for (let i = min; i <= max; i++) {
sum += i;
}
return sum;
}

[Link](calculateSum(1, 10)); // Output: 55

Output

55

Advanced Function Concepts


In advanced JavaScript, functions can become more complex and powerful. Here are some advanced concepts:

Higher-Order Functions

Functions that take other functions as arguments or return functions are called higher-order functions.

Closures

A closure is a function that retains access to its outer scope even after the outer function has returned.

First-Class Functions

In JavaScript, functions are first-class citizens. This means functions can be assigned to variables, passed as
arguments, and returned from other functions.

Summary
Functions are an essential part of JavaScript programming. They allow you to create reusable blocks of code,
which makes your programs more modular and easier to maintain. By understanding and using functions
effectively, you can write more efficient and readable code.

In this lesson, we covered:

 Basic function syntax and how to declare functions.


 Calling functions and the concept of parameters and arguments.
 Handling missing arguments.
 Creating a practical example function to sum numbers in a range.

Anonymous Functions

Anonymous functions in JavaScript are functions without a name or identity. They are often used when a
function is only needed once or as an argument to other functions. Let's dive deeper into what anonymous
functions are, how they work, and where they can be applied.

What are Anonymous Functions?


An anonymous function is simply a function that does not have a name. This can be useful in various scenarios,
such as callbacks, event handlers, or immediately invoked function expressions (IIFE).

Basic Syntax

The basic syntax for creating an anonymous function looks like this:

let anonymousFunction = function() {


[Link]("Hello from GeeksforGeeks!");
};
Here, anonymousFunction is a variable that holds the anonymous function. To call this function, you simply use
the variable name followed by parentheses:

anonymousFunction(); // Output: Hello from GeeksforGeeks!

Function Expression

When you assign an anonymous function to a variable, it is known as a function expression. This makes the
variable a function, not just a simple variable.

let greet = function() {


[Link]("Hello from GeeksforGeeks!");
};

greet(); // Output: Hello from GeeksforGeeks!

Type of Anonymous Function

To confirm that the variable holding the anonymous function is indeed a function, you can use
the typeof operator:
[Link](typeof greet); // Output: function

Hoisting and Anonymous Functions

Unlike function declarations, anonymous functions assigned to variables do not get hoisted in the same way.
This means you cannot call them before they are defined.

greet(); // Error: Cannot access 'greet' before initialization

let greet = function() {


[Link]("Hello from GeeksforGeeks!");
};

Named Function Expressions


A named function expression is an anonymous function with a name. This name is local to the function's scope
and can be useful for recursion or debugging.

let greet = function greetMessage() {


[Link]("Hello from GeeksforGeeks!");
};

greet(); // Output: Hello from GeeksforGeeks!

Calling the Named Function

While you can call the named function using the variable it is assigned to, trying to call the function by its name
outside of its scope will result in an error.

greetMessage(); // Error: greetMessage is not defined


Inside the function, however, the name can be used for recursive calls:

let factorial = function fact(n) {


if (n <= 1) return 1;
return n * fact(n - 1);
};

[Link](factorial(5)); // Output: 120

Practical Use Cases


Callback Functions
Anonymous functions are commonly used as callback functions, especially in asynchronous operations like event
handling, timers, or AJAX requests.

setTimeout(function() {
[Link]("This is a callback function!");
}, 1000);

Immediately Invoked Function Expressions (IIFE)

An IIFE is a function that is executed immediately after it is defined. This is often used to create a new scope to
avoid polluting the global scope.

(function() {
[Link]("IIFE executed immediately!");
})();

Event Handlers

Anonymous functions are frequently used in event handling for adding interactivity to web pages.

[Link]("myButton").addEventListener("click", function() {
alert("Button was clicked!");
});

Conclusion
Anonymous functions are a powerful feature in JavaScript that allow for more flexible and concise code. By
understanding and using them effectively, you can write cleaner, more maintainable code. Whether you're
using them as callbacks, in IIFEs, or as event handlers, anonymous functions provide a versatile tool for
JavaScript developers.

Summary

 Anonymous Functions: Functions without a name, often used as function expressions.


 Function Expressions: Assigning functions to variables to be used as needed.
 Named Function Expressions: Anonymous functions with a local name for recursion or debugging.
 Use Cases: Callbacks, IIFEs, event handlers, and more.

Arrow Function
Introduction

Arrow functions, also known as fat arrow functions, are a more concise way to write functions in JavaScript.
Introduced in ECMAScript 6 (ES6), arrow functions provide a shorter syntax for writing functions and come
with some significant benefits and differences compared to regular functions. In this article, we will explore
arrow functions, how they differ from regular functions, and their advantages.

Basic Syntax of Arrow Functions


Arrow functions offer a more concise syntax for writing function expressions. Here is an example of how a
regular function expression can be transformed into an arrow function.

Regular Function Expression:

let calculateSum = function(x, y) {


return x + y;
};

[Link](calculateSum(12, 4)); // Output: 16

Arrow Function

let calculateSum = (x, y) => {


return x + y;
};

[Link](calculateSum(12, 4)); // Output: 16


In the arrow function, we replace the function keyword with the arrow syntax =>.

Simplifying Arrow Functions


Arrow functions can be further simplified when they have a single expression to return. In such cases,
the return keyword and the curly braces {} can be omitted.

Simplified Arrow Function

let calculateSum = (x, y) => x + y;

[Link](calculateSum(12, 18)); // Output: 30


In this simplified form, the expression x + y is implicitly returned.

Handling Single Parameters


When an arrow function has only one parameter, the parentheses around the parameter can be omitted.

Single Parameter Example

let square = x => x * x;

[Link](square(5)); // Output: 25
If there are no parameters, empty parentheses are used:

let greet = () => [Link]("Hello from GFG!");

greet(); // Output: Hello from GFG!

Arrow Functions and Lexical this


One of the most significant differences between arrow functions and regular functions is how they handle
the this keyword. Arrow functions do not have their own this context; they inherit this from the surrounding
non-arrow function or the global context.

Example of Lexical this

function Person() {
[Link] = 0;

setInterval(() => {
[Link]++; // `this` refers to the Person object
[Link]([Link]);
}, 1000);
}

let p = new Person();


In the example above, the arrow function inside setInterval inherits this from the Person function, ensuring
that [Link] refers to the age property of the Person instance.

Advanced Arrow Function Examples


Conditional Logic in Arrow Functions
When you need to perform conditional logic inside an arrow function, you can use curly braces {} to define the
function body and include the return statement.

let calculateSumOrDifference = (x, y) => {


if (x > y) {
return x + y;
} else {
return x - y;
}
};

[Link](calculateSumOrDifference(31, 12)); // Output: 43


[Link](calculateSumOrDifference(11, 12)); // Output: -1

Using Ternary Operators

For simple conditional logic, ternary operators can be used to keep the arrow function concise.

let calculateSumOrDifference = (x, y) => x > y ? x + y : x - y;

[Link](calculateSumOrDifference(31, 12)); // Output: 43


[Link](calculateSumOrDifference(11, 12)); // Output: -1

Best Practices and Usage


Arrow functions are best suited for non-method functions and callbacks where the this context is not required or
should be inherited from the surrounding scope.

Examples

1. Event Handlers (when not using this):

[Link]("myButton").addEventListener("click", () => {
[Link]("Button clicked!");
});
2 Array Methods:

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


let squares = [Link](x => x * x);

[Link](squares); // Output: [1, 4, 9, 16, 25]


JS Iterating Over String

Congratulations on completing the initial modules! Now we are moving into more complex topics such as arrays
and objects, and understanding their methods. This module will focus on iterating over a string, a
fundamental skill that will be useful for manipulating and analyzing text data.

Iterating Over a String

When iterating over a string, you often need to perform tasks such as searching for a character, counting
occurrences, or manipulating individual characters.

Example 1: Printing Each Character


Let's start with a simple example where we print each character of a string on a new line.

let message = "I am learning JavaScript";

// Iterate over each character in the string


for (let i = 0; i < [Link]; i++) {
[Link](message[i]);
}

Output

a
m

l
e
a
r
n
i
n
g

J
a
v
a
S
c
r
i
p
t

In this example, the for loop iterates over each character of the string message using its index.

Example 2: Breaking the Loop on a Specific Character


Suppose we want to stop iterating when we encounter the character 'n':

for (let i = 0; i < [Link]; i++) {


if (message[i] === 'n') {
break;
}
[Link](message[i]);
}
This loop prints each character until it encounters 'n', at which point it breaks out of the loop.

Example 3: Counting Occurrences of a Character


Let's count how many times the character 'a' appears in the string:

let count = 0;

for (let i = 0; i < [Link]; i++) {


if (message[i] === 'a') {
count++;
}
}

[Link]("The character 'a' appears " + count + " times.");


This loop increments the count variable each time it encounters 'a'.

Example 4: Using Index to Print Specific Characters


Now, let's use the index to print specific characters. We will print the character at index 1, 2, and 3.

[Link](message[1]); // Prints ' '


[Link](message[2]); // Prints 'a'
[Link](message[3]); // Prints 'm'

Using the for...of Loop

The for...of loop is a cleaner and more readable way to iterate over the elements of an iterable object, such as a
string.

Example 5: Using for...of to Print Each Character

for (let char of message) {


[Link](char);
}
This loop automatically iterates over each character in the string.

Practical Use Cases

Use Case 1: Finding the Index of a Character


You might want to find the position of a character within a string.

for (let i = 0; i < [Link]; i++) {


if (message[i] === 'a') {
[Link]("Index of 'a': " + i);
}
}
This loop prints the index each time it encounters 'a'.

Use Case 2: Filtering Characters


Suppose we want to create a new string containing only the vowels from the original string.

let vowels = '';


const vowelSet = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);

for (let char of message) {


if ([Link](char)) {
vowels += char;
}
}

[Link](vowels);
This code creates a new string with only the vowels from the original string.

Summary

Iterating over a string is a fundamental operation in JavaScript that allows you to perform various tasks such as
searching, counting, and manipulating characters. You can use traditional for loops or the more
modern for...of loop for these purposes.

JS String Method - charAt & charCodeAt

Introduction to String Methods

String methods are built-in functions that perform various operations on strings. They can help you find the
position of a character, determine the length of a string, convert cases, and much more. Let's explore some
of these methods.

Basic String Methods

1. Finding the Length of a String


The length property returns the length of a string.

let message = "I am a mentor at GeeksforGeeks";


[Link]([Link]); // Output: 30

Output

30

1. Finding a Character at a Specific Index


The charAt method returns the character at a specified index.

let index = 5;
[Link]([Link](index)); // Output: a
1. Finding the ASCII Code of a Character
The charCodeAt method returns the ASCII code of the character at a specified index.

[Link]([Link](index)); // Output: 97

[Link]()

[Link]() Returns character at given index of string.


character = [Link](index)

Arguments: The only argument to this function is the index in the string from where the single character is to be
extracted. The range of this index is between 0 and length - 1, including the limits. If no index is specified
then the first character of the string is returned as 0 is the default index used for this function. Return
value This function returns a single character located at the index specified as the argument to the function.
If the index is out of range, then this function returns an empty string.

Example 1:

function func() {

// Original string
var str = 'JavaScript is object oriented language';

// Finding the character at given index


var value = [Link](0);
var value1 = [Link](4);
[Link](value);
[Link](value1);
}
func();

Output

J
S
Example 2:

In this example the function charAt() finds the character at index 50. Since the index is out of bounds for the
given string therefore the function returns "" an empty string.

// JavaScript to illustrate charAt() function


function func() {

// Original string
var str = 'JavaScript is object oriented language';

// Finding the character at given index


var value = [Link](50);
[Link]("Char at index 50 is: "+value);
}
func();

Output

Char at index 50 is:

Working with String Methods

Let's use these methods to perform various tasks.

Example: Using charAt and charCodeAt

let message = "I am a mentor at GeeksforGeeks";


let index = 2;

// Using charAt
let char = [Link](index);
[Link](`Character at index ${index}: ${char}`); // Output: a

// Using charCodeAt
let asciiCode = [Link](index);
[Link](`ASCII code of character at index ${index}: ${asciiCode}`); // Output: 97
[Link]()

[Link]() method returns a Unicode character set code unit of the character present at the index in the
string specified as the argument. The syntax of the method is as follows:
[Link](index)

Arguments The only argument to this method is the index of the character in the string whose Unicode is to be
used. The range of the index is from 0 to length - 1. Return value This method returns the Unicode (ranging
between 0 and 65535) of the character whose index is provided to the method as the argument. If the index
provided is out of range this method returns NaN.

Example 1:

In this example the method charCodeAt() extracts the character from the string at index 4. Since this character
is m, therefore this method returns the Unicode sequence as 109.

// JavaScript to illustrate charCodeAt() method

function func() {
var str = 'ephemeral';

// Finding the code of the character at


// given index
var value = [Link](4);
[Link](value);
}

func();

Output

109

Example 2:

In this example the method charCodeAt() extracts the character from the string at index 20. Since the index is
out of bounds for the string, therefore this method returns the answer as NaN.

// JavaScript to illustrate charCodeAt() method

function func() {
var str = 'ephemeral';

// Finding the code of the character


// at given index
var value = [Link](20);

[Link](value);
}
func();

Output
NaN

JS String Method - indexOf()

Congratulations on completing the previous modules! Now, let's dive deeper into JavaScript by exploring
the indexOf method, which is used to find the index of a particular character or substring in a given string.
This method is very useful when you need to determine whether a character or substring exists in a string
and where it is located.

Understanding the indexOf Method

The indexOf method returns the index within the calling string of the first occurrence of the specified value,
starting the search at fromIndex. It returns -1 if the value is not found.

[Link]() function finds the index of the first occurrence of the argument string in the given string. The value
returned is 0-based. The syntax of the function is as follows:
[Link](searchValue , index)

Arguments:
The first argument to the function searchValue is the string that is to be searched in the base string. The
second argument to the function index defines the starting index from where the searchValue is to be
searched in the base string.

Return value:
This function returns the index of the string (0-based) where the searchValue is found for the first time. If
the searchValue cannot be found in the string then the function returns -1.

Example 1:

In this example, the function indexOf() finds the index of the string Train. Since the first and the only index
where this string is present is 9, therefore this function returns 9 as the answer.

// JavaScript to illustrate indexOf() function


function func() {

// Original string
var str = 'Departed Train';

// Finding index of occurrence of 'Train'


var index = [Link]('Train');
[Link](index);
}
func();

Output

Example 2:

In this example, the function indexOf() finds the index of the string ed Tr. Since the first and the only index
where this string is present is 6, therefore this function returns 6 as the answer.

// JavaScript to illustrate indexOf() function


function func() {

// Original string
var str = 'Departed Train';

// Finding index of occurrence of 'Train'


var index = [Link]('ed Tr');
[Link](index);
}
func();

Output

Example 3:

In this example, the function indexOf() finds the index of the string Train. Since the searchValue is not present in
the string, therefore this function returns -1 as the answer.

// JavaScript to illustrate indexOf() function


function func() {

// Original string
var str = 'Departed Train';

// Finding index of occurrence of 'Train'


var index = [Link]('train');
[Link](index);
}
func();

Output

-1

JS String Method - includes()

The includes method in JavaScript is a powerful tool for checking whether a given substring or character exists
within a string. Unlike the indexOf method, which also serves a similar purpose, includes directly returns a
Boolean value (true or false), making it more straightforward for conditional checks.

In JavaScript, includes() method determines whether a string contains the given characters within it or not. This
method returns true if the string contains the characters, otherwise, it returns false.

Note: The includes() method is case sensitive i.e, it will treat the Uppercase characters and Lowercase
characters differently.

Syntax:
[Link](searchvalue, start)

Parameters Used:

 search value: It is the string in which the search will take place.
 start: This is the position from where the search will be processed
(although this parameter is not necessary if this is not mentioned the search will begin from the start
of the string).
 Returns either a Boolean True indicating the presence or it returns a False indicating the absence.

Example 1:

var str = "Welcome to GeeksforGeeks.";


var check = [Link]("Geeks");
if(check){
[Link]("present");
}
else{
[Link]("not present");
}

Output

present

Explanation: Since the second parameter is not defined, the search will take place from the starting index.
And it will search for Geeks, as it is present in the string, it will return a true.

Example 2:

var str = "Welcome to GeeksforGeeks.";


var check = [Link]("geeks");
[Link](check);

Output

false

Explanation: Even in this case the second parameter is not defined, so the search will take place from the
starting index. But as this method is case sensitive it will treat the two strings differently, hence returning a
boolean false.

Example 3:

var str = "Welcome to GeeksforGeeks.";


var check = [Link]("o",18);
[Link](check);

Output

false

Explanation: In this case the second parameter is 18, so the search will take place from index 18, and since there
is no 'o' after index 18, it returns false.
Exceptions :

 The search will not be processed if the second parameter i.e computed index(starting index) is
greater than or equal to the string length and hence return false.

var str = "Welcome to GeeksforGeeks.";


var check = [Link]("o",30);
[Link](check);

Output

false

 If the computed index(starting index) i.e the position from which the search will begin is less than 0,
the entire array will be searched.

var str = "Welcome to GeeksforGeeks.";


var check = [Link]("o",-2);
[Link](check);

Output

true

Practical Application: Checking for Vowels

Let's extend this example to check if a string contains any vowels.

const displayMessage = "I love to code in light mode.";


const vowels = "aeiouAEIOU";

for (let character of displayMessage) {


if ([Link](character)) {
[Link](`${character} is a vowel`);
}
}

Output

I is a vowel
o is a vowel
e is a vowel
o is a vowel
o is a vowel
e is a vowel
i is a vowel
i is a vowel
o is a vowel
e is a vowel

Practical Application: Conditional Checks

Using includes, you can create conditional checks without needing to compare values explicitly with true or false.

Example:

const displayMessage = "I love to code in light mode.";

if ([Link]("light")) {
[Link]("Person loves to code in light mode.");
} else {
[Link]("Person loves to code in dark mode.");
}

Output

Person loves to code in light mode.

Using includes for More Complex Conditions

Combining multiple methods and conditions can lead to very powerful and flexible code.

Example:

const message = "Prakash@[Link]";


const checkString = "light";

if ([Link]().includes([Link]())) {
[Link]("The string includes the word 'light' in any case.");
} else {
[Link]("The string does not include the word 'light'.");
}

Conclusion

The includes method is a versatile and straightforward way to check for the presence of substrings or characters
in a string. Its Boolean return type makes it especially useful for conditional logic. Understanding how to
use includes effectively can simplify your code and enhance its readability and maintainability. Keep
experimenting with these methods to find the best ways to apply them in your projects.

JS String Method - toUpperCase() and toLowerCase()

In JavaScript, we can easily convert strings to different cases using the built-in
methods toLowerCase and toUpperCase. These methods are particularly useful in various scenarios, such as
comparing user input in a case-insensitive manner or formatting text for display.

The toLowerCase Method

The toLowerCase method converts all characters in a string to lowercase.

[Link]()

[Link]() method converts the entire string to Upper case. This method does not affect any of the
special characters, digits, and the alphabets that are already in the upper case.

Syntax:
[Link]()

Return value:
This method returns a new string in which all the lower case letters are converted to upper case.

Example 1:

function func() {
var str = 'geeksforgeeks';
var string = [Link]();
[Link](string);
}
func();

Output
GEEKSFORGEEKS

In this example the method toUpperCase() converts all the lower case alphabets to their upper case equivalents.

Example 2:

function func() {
var str = 'geeksforgeeks#@';
var string = [Link]();
[Link](string);
}
func();

Output

GEEKSFORGEEKS#@

In this example the method toUpperCase() converts all the lower case alphabets to their upper case equivalents
without affecting the special characters and the digits.

[Link]()

[Link]() method converts the entire string to lower case. This method does not affect any of the
special characters, digits, and the alphabets that are already in the lower case.

Syntax:
[Link]()

Return value:
This method returns a new string in which all the upper case letters are converted to lower case.

Example 1:

function func() {
var str = 'GEEKSFORGEEKS';
var string = [Link]();
[Link](string);
}
func();

Output
geeksforgeeks

In this example, the method toLowerCase() converts all the upper case alphabets into lower case alphabets
without affecting all those characters that are already in the lower case.

Example 2:

function func() {
var str = 'GEEKSFORGEEKS@123';
var string = [Link]();
[Link](string);
}
func();

Output

geeksforgeeks@123

In this example the method toLowerCase() converts all the upper case alphabets into lower case alphabets
without affecting the special characters, digits and all those characters that are already in lower case.

Conclusion

Converting strings to different cases is a simple yet powerful technique in JavaScript. It helps in normalizing text
for comparison, ensuring consistent formatting, and improving user experience. Understanding and utilizing
methods like toLowerCase and toUpperCase can significantly enhance your ability to handle strings effectively
in your projects.

JS String Method - substring()

The substring method in JavaScript is incredibly useful for extracting parts of a string. It allows you to specify
a start and end index to extract a portion of the string. Here's how you can make the most of this method.

What is the substring Method?

The substring method returns a part of the string between the start and end indexes, or to the end of the
string if the end index is omitted. The character at the end index is not included.

Syntax:

[Link](Startindex, Endindex)
 start: The index where to start the extraction. The first character's index is 0.
 end (optional): The index before which to end the extraction. The character at this index will not be
included.
Return value: It returns a new string which is part of the given string.

JavaScript code to show the working of [Link]() function:


Example 1:

// Taking a string as variable


var string = "geeksforgeeks";
a = [Link](0, 4)
b = [Link](1, 6)
c = [Link](5)
d = [Link](0)

// Printing new string which are


// the part of the given string
[Link](a);
[Link](b);
[Link](c);
[Link](d);

Output

geek
eeksf
forgeeks
geeksforgeeks

Example 2:
Index always start with 0. If still we take index as negative, it will be considered as zero and index can't be in
fraction if it is found so, it will be converted into its just lesser whole number.

// Taking a string as variable


var string = "geeksforgeeks";
a = [Link](-1)
b = [Link](2.5)
c = [Link](2.9)

// Printing new string which are


// the part of the given string
[Link](a);
[Link](b);
[Link](c);

Output

geeksforgeeks
eksforgeeks
eksforgeeks

Practical Use Case: Truncating Long Names


Let's consider a practical scenario where you need to display a username on a card, but if the username is
too long, you want to truncate it and add ellipses (...).

const username = "prakashnarsingrao sakari";


const maxLength = 10;
let displayName = username;

if ([Link] > maxLength) {


displayName = [Link](0, maxLength) + "...";
}

[Link](displayName); // Output: "prakashnar..."

Output

prakashnar...

Responsive Design Example

In responsive design, you might want to show a truncated version of text on smaller screens and the full
version on larger screens.

const username = "prakashnarsingrao sakari";


const maxLength = 10;

function getDisplayName(username, maxLength) {


return [Link] > maxLength ? [Link](0, maxLength) + "..." : username;
}

const displayName = getDisplayName(username, maxLength);


[Link](displayName); // Output: "prakashnar..."
Output

prakashnar...

Substring vs. Slice

While both substring and slice can be used to extract parts of a string, they have subtle differences. The main
difference is in how negative indices are handled.

 substring: Treats negative indices as 0.


 slice: Allows negative indices, counting from the end of the string.

const username = "prakashnarsingrao sakari";

// Using substring
[Link]([Link](0, 10)); // Output: "prakashnar"

// Using slice
[Link]([Link](0, 10)); // Output: "prakashnar"

// Using slice with negative indices


[Link]([Link](-10)); // Output: "rao sakari"

Output

prakashnar
prakashnar
rao sakari

Conclusion

The substring method is a powerful tool for working with strings in JavaScript. It allows you to easily extract
parts of a string and is particularly useful for scenarios like truncating text for display purposes.
Understanding and utilizing this method can greatly enhance your ability to handle strings in your projects.

JS String Method - trim()


Congratulations on making it this far! We're almost at the end of our string methods module. The last method
we'll cover is the trim method, which is particularly useful for cleaning up strings by removing unwanted
spaces from both ends.

What is the trim Method?

The trim method removes whitespace from both ends of a string. Whitespace in this context includes spaces,
tabs, and any line break characters.

[Link]() method is used to remove the white spaces from both the ends of the given string.

Syntax:
[Link]()

Return value:

This method returns a new string, without any of the leading or the trailing white spaces.

Why Use the trim Method?

Leading and trailing spaces can cause issues, especially when processing user input. For instance, if you ask a
user to enter their name, they might inadvertently include spaces at the beginning or end. Using trim helps
ensure you work with clean data.

Basic Usage of trim

Let's look at a practical example to understand how the trim method works.

Example 1: In this example the trim() method removes all the leading and the trailing spaces in the string str.

function func() {
var str = " GeeksforGeeks ";
var st = [Link]();
[Link](st);
}
func();

Output

GeeksforGeeks

Practical Use Cases

Cleaning User Input


Consider a scenario where you want to get the first six characters of a user's name, but the input might have
leading or trailing spaces.

let userInput = " Hola, I love GFG ";


[Link]("Original length:", [Link]); // Output: 25

let cleanedInput = [Link]();


[Link]("Trimmed length:", [Link]); // Output: 17
[Link]("Trimmed input:", cleanedInput); // Output: "Hola, I love GFG"

let firstSixChars = [Link](0, 6);


[Link]("First 6 characters:", firstSixChars); // Output: "Hola, "

Note: Trim is used to remove white spaces only from the start and end of a string and not from in-between.

function func() {
var str = " Geeks for Geeks ";
var st = [Link]();
[Link](st);
}
func();

Output

Geeks for Geeks

[Link]() method is used to remove the white spaces from the start of the given string. It does not affect the
trailing white spaces.

Syntax:
[Link]()

Return value:

This method returns a new string, without any of the leading white spaces.

function func() {
var str = " Geeks for Geeks ";
var st = [Link]();
[Link](st);
}
func();
Output

Geeks for Geeks

[Link]() method is used to remove the white spaces from the end of the given string. It does not affect
the white spaces at the start of the string.

Syntax:
[Link]()

Return value:

This method returns a new string, without any of the trailing white spaces.

function func() {
var str = " Geeks for Geeks ";
var st = [Link]();
[Link](st);
}
func();

Output

Geeks for Geeks

Key Points

1. Trim Leading and Trailing Spaces: The trim method is useful for removing unwanted spaces from the
start and end of a string.
2. Improves Data Quality: Especially useful for cleaning up user input before further processing.
3. Supports Method Chaining: You can chain trim with other string methods to write more concise and
readable code.

Conclusion

The trim method is a powerful tool for cleaning up strings and ensuring you work with the correct data. By
removing unwanted spaces, you can avoid potential issues in your applications.

Basic Properties of Arrays and Iterating over Array


In JavaScript, primitive data types include strings, numbers, booleans, undefined, and null. However, non-
primitive data types, such as arrays, provide a way to store and manage collections of data efficiently. This
guide will explain the use of arrays, their advantages, and practical applications.

Why Use Non-Primitive Data Types?

Consider a scenario where you need to store the names of 60 students. Using individual variables for each name
would be inefficient and cumbersome
let student1 = "Prakash";
let student2 = "Ashish";
let student3 = "Via";
let student4 = "Adarsh";
// ... and so on up to 60 students

Instead, arrays allow us to store multiple items in a single variable, making the code more manageable and
reducing memory usage.

Creating and Using Arrays

Creating an Array
You can create an array using square brackets [] and separate items with commas:

let studentNames = ["Prakash", "Ashish", "Via", "Adarsh"];


[Link](studentNames); // Output: ["Prakash", "Ashish", "Via", "Adarsh"]

Adding Different Types of Data


Arrays can store multiple data types, including numbers, strings, other arrays, and objects:

let mixedArray = ["Prakash", 42, [1, 2, 3], { schoolName: "SIES" }];


[Link](mixedArray);
// Output: ["Prakash", 42, [1, 2, 3], { schoolName: "SIES" }]

Accessing Array Elements

Array elements are accessed using their index, which starts at 0:

[Link](studentNames[0]); // Output: "Prakash"


[Link](studentNames[1]); // Output: "Ashish"
Iterating Over Arrays

Using a For Loop


You can iterate over an array using a for loop:

for (let name of studentNames) {


[Link](name);
}
// Output: "Prakash", "Ashish", "Via", "Adarsh"

Using a For-In Loop

The for-in loop iterates over the indices of the array:

for (let index in studentNames) {


[Link](studentNames[index]);
}
// Output: "Prakash", "Ashish", "Via", "Adarsh"

Modifying Arrays

Adding Elements
You can add elements to an array using the push method:

[Link]("Piyush");
[Link](studentNames);
// Output: ["Prakash", "Ashish", "Via", "Adarsh", "Piyush"]

Removing Elements
To remove elements, you can use methods like pop, shift, and splice:

[Link](); // Removes the last element


[Link](studentNames);
// Output: ["Prakash", "Ashish", "Via", "Adarsh"]

[Link](); // Removes the first element


[Link](studentNames);
// Output: ["Ashish", "Via", "Adarsh"]
[Link](1, 1); // Removes one element at index 1
[Link](studentNames);
// Output: ["Ashish", "Adarsh"]

Array Methods

JavaScript provides various array methods to manipulate data:

map

Creates a new array with the results of calling a function for every array element:

let upperCaseNames = [Link](name => [Link]());


[Link](upperCaseNames); // Output: ["ASHISH", "ADARSH"]

filter

Creates a new array with elements that pass a test provided by a function:

let longNames = [Link](name => [Link] > 5);


[Link](longNames); // Output: ["Ashish", "Adarsh"]
Using Reduce

It is used to reduce the array into one single value using some functional logic

array = [ 1, 2, 3, 4, 5, 6 ];

const helperSum = (acc,curr) => acc+curr


sum = [Link](helperSum, 0);

[Link](array)
[Link](sum);

Output

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

Using Some

It is used to check whether some array values passes a test


array = [ 1, 2, 3, 4, 5, 6 ];

const lessthanFourCheck = (element) => element < 4 ;


const lessthanFour = [Link](lessthanFourCheck)

[Link](array);
if(lessthanFour){
[Link]("At least one element is less than 4" )
}else{
[Link]("All elements are greater than 4 ")
}

Output

[ 1, 2, 3, 4, 5, 6 ]
At least one element is less than 4

Conclusion

Arrays in JavaScript offer a powerful way to handle collections of data. They allow you to store multiple items in
a single variable, perform complex operations, and make your code more efficient and readable. By
mastering arrays and their methods, you can greatly enhance your ability to manage and manipulate data in
JavaScript.

Array push, pop and slice methods

Introduction

In this lesson, we'll explore three methods in JavaScript that allow us to delete elements from an array: pop, slice,
and splice. These methods are crucial for managing arrays effectively, enabling us to remove elements in
different ways.

Array push() Method

The [Link]() method is used to push one or more values into the array. This method changes the length of the
array by the number of elements added to the array.

Syntax:
[Link](element1, elements2 ....., elementN)
Parameters: This method contains as many numbers of parameters as the number of elements to be inserted
into the array. Return value: This method returns the new length of the array after inserting the arguments
into the array.

Below is an example of Array push() method.

Example:

function func() {
var arr = ['GFG', 'gfg', 'g4g'];

// Pushing the element into the array


[Link]('GeeksforGeeks');
[Link](arr);

}
func();

Output

[ 'GFG', 'gfg', 'g4g', 'GeeksforGeeks' ]

Example 1: In this example, the function push() adds the numbers to the end of the array.
var arr = [34, 234, 567, 4];
print([Link](23,45,56));
print(arr);

Output:
7
34,234,567,4,23,45,56

Example 2: In this example, the function push() adds the objects to the end of the array.

var arr = [34, 234, 567, 4];


print([Link]('jacob',true,23.45));
print(arr);

Output:
7
34,234,567,4,jacob,true,23.45

More example codes for the above method are as follows:

Program 1:
function func() {
// Original array
var arr = [34, 234, 567, 4];

// Pushing the elements


[Link]([Link](23,45,56));
[Link](arr);
}
func();

Output

7
[
34, 234, 567, 4,
23, 45, 56
]

Array pop() Method

The [Link]() method is used to remove the last element of the array and also returns the removed element.
This function decreases the length of the array.

Syntax:
[Link]()

Parameters: This method does not accept any parameter.

Return value This method returns the removed element array. If the array is empty, then this function returns
undefined.

Below is an example of Array pop() method.

Example:

function func() {
var arr = ['GFG', 'gfg', 'g4g', 'GeeksforGeeks'];

// Popping the last element from the array


[Link]([Link]());
}
func();
Output

GeeksforGeeks

Example 1: In this example, the pop() method removes the last element from the array, which is 4, and returns
it.
var arr = [34, 234, 567, 4];
var popped = [Link]();
print(popped);
print(arr);

Output:
4
34,234,567

Example 2: In this example, the function pop() tries to extract the last element of the array but since the array is
empty therefore it returns undefined as the answer.
var arr = [];
var popped = [Link]();
print(popped);

Output:
undefined

More example codes for the above method are as follows :

Program 1:

function func() {
var arr = [34, 234, 567, 4];

// Popping the last element from the array


var popped = [Link]();
[Link](popped);
[Link](arr);
}
func();

Output

4
[ 34, 234, 567 ]
Program 2:

function func() {
var arr = [];

// popping the last element


var popped = [Link]();
[Link](popped);
}
func();

Output

undefined

Array slice() Method

The arr. slice() method returns a new array containing a portion of the array on which it is implemented.
The original remains unchanged.

Syntax:
[Link](begin, end)

Parameters: This method accepts two parameters as mentioned above and described below:

begin: This parameter defines the starting index from where the portion is to be extracted. If this
argument is missing then the method takes begin as 0 as it is the default start value.
 end: This parameter is the index up to which the portion is to be extracted (excluding the end index).
If this argument is not defined then the array till the end is extracted as it is the default end value If
the end value is greater than the length of the array, then the end value changes to the length of the
array.
Return value: This method returns a new array containing some portion of the original array.

Below is an example of the Array slice() method.

Example:

function func() {
// Original Array
var arr = [23,56,87,32,75,13];
// Extracted array
var new_arr = [Link](2,4);
[Link](arr);
[Link]("<br>");
[Link](new_arr);
}
func();

Output

[ 23, 56, 87, 32, 75, 13 ]


<br>
[ 87, 32 ]

Example 1: In this example, the slice() method extracts the entire array from the given string and returns it as
the answer since no arguments were passed to it.
var arr = [23,56,87,32,75,13];
var new_arr = [Link]();
[Link](arr);
[Link](new_arr);

Output:
[23,56,87,32,75,13]
[23,56,87,32,75,13]

Example 2: In this example, the slice() method extracts the array starting from index 2 till the end of the array
and returns it as the answer.
var arr = [23,56,87,32,75,13];
var new_arr = [Link](2);
[Link](arr);
[Link](new_arr);

Output:
[23,56,87,32,75,13]
[87,32,75,13]

Example 3: In this example, the slice() method extracts the array from the given array starting from index 2 and
including all the elements less than the index 4.
var arr = [23,56,87,32,75,13];
var new_arr = [Link](2,4);
[Link](arr);
[Link](new_arr);

Output:
[23,56,87,32,75,13]
[87,32]

The code for the above method is provided below:

Program 1:

function func() {
//Original Array
var arr = [23,56,87,32,75,13];
//Extracted array
var new_arr = [Link]();
[Link](arr);
[Link]("<br>");
[Link](new_arr);
}
func();

Output

[ 23, 56, 87, 32, 75, 13 ]


<br>
[ 23, 56, 87, 32, 75, 13 ]

Program 2:

function func() {
//Original Array
var arr = [23,56,87,32,75,13];
//Extracted array
var new_arr = [Link](2);
[Link](arr);
[Link]("<br>");
[Link](new_arr);
}
func();

Output

[ 23, 56, 87, 32, 75, 13 ]


<br>
[ 87, 32, 75, 13 ]

Conclusion
The pop, slice, and splice methods provide powerful ways to manage and manipulate arrays in JavaScript.
Understanding these methods allows for more efficient and effective data handling, especially when working
with large datasets or developing complex applications. Keep practicing these methods to gain proficiency in
array manipulation.

Array Includes and sort methods

Array includes() Method

The [Link]() method is used to know either a particular element is present in the array or not and
accordingly, it returns true or false i.e, if the element is present, then it returns true otherwise false.

Syntax:
[Link](searchElement, start)

Parameter: This method accepts two parameters as mentioned above and described below:

searchElement: This parameter holds the element which will be searched.


start: This parameter is optional and it holds the starting point of the array, where to begin the
search the default value is 0.
Return Value: It returns a Boolean value i.e, either True or False.

Below examples illustrate the Array includes() method in JavaScript:

 Example 1: In this example the method will searched for the element 2 in that array.
Input : [1, 2, 3, 4, 5].includes(2);
Output: true

 Example 2: In this example the method will searched for the element 9 in that array.
Input : [1, 2, 3, 4, 5].includes(9);
Output: false

Code for the above method is provided below:

Program 1:

// Taking input as an array A


// having some elements.
var A = [ 1, 2, 3, 4, 5 ];
// includes() method is called to
// test whether the searching element
// is present in given array or not.
a = [Link](2)

// Printing result of includes().


[Link](a);

Output

true

Program 2:

// Taking input as an array A


// having some elements.
var name = [ 'gfg', 'cse', 'geeks', 'portal' ];

// includes() method is called to


// test whether the searching element
// is present in given array or not.
a = [Link]('cat')

// Printing result of includes()


[Link](a);

Output

false

Array sort() Method

The [Link]() method is used to sort the array in place in a given order according to the compare() function. If
the method is omitted then the array is sorted in ascending order.

Syntax:
[Link](compareFunction)

Parameters: This method accepts a single parameter as mentioned above and described below:

compareFunction: This parameter is used to sort the elements according to different attributes and in a different
order.
 compareFunction(a,b) < 0
 compareFunction(a,b) > 0
 compareFunction(a,b) = 0
Return value: This method returns the reference of the sorted original array.

Below is an example of Array sort() method.

Program 1:

// JavaScript to illustrate sort() function


function func() {

// Original string
var arr = ["Geeks", "for", "Geeks"]

[Link](arr);
// Sorting the array
[Link]([Link]());
}
func();

Output

[ 'Geeks', 'for', 'Geeks' ]


[ 'Geeks', 'Geeks', 'for' ]

Example 1: In this example, the sort() method arranges the elements of the array in ascending order.
var arr = [2, 5, 8, 1, 4]
[Link]([Link]());
[Link](arr);

Output:
1,2,4,5,8
1,2,4,5,8

Example 2: In this example, the sort() method the elements of the array are sorted according to the function
applied on each element.
var arr = [2, 5, 8, 1, 4]
[Link]([Link](function(a, b) {
return a + 2 * b;
}));
[Link](arr);

Output:
2,5,8,1,4
2,5,8,1,4

Example 3: In this example, we use the sort() method on the array of numbers & observe some unexpected
behavior.
let numbers = [20,5.2,-120,100,30,0]
[Link]([Link]())

Output:
-120,0,100,20,30,5.2

Our output should be -120, 0, 5.2, 20, 30, 100 but it’s not so, why? Because as we apply the direct sort() method,
it would process accordingly: 100 would be placed before 20, as ‘2’ is larger than ‘1’, and similarly in the case
of 30 & 5.2, as ‘5’ is larger than ‘3’ thus, 30 would be placed before 5.2. We can resolve this unexpected
error by using the sort() method for numerics using the following compare function:
let numbers = [20,5.2,-120,100,30,0];

/* Logic:
20 - (5.2) = +ve => 5.2 would be placed before 20,
20 - (-120) = +ve => -120 would be placed before 20,
20 - (100) = -ve => 100 would be placed after 20,
20 - (30) = -ve => 30 would be placed after 20,
20 - (0) = +ve => 0 would be placed before 20,
Similarly for every element, we check and place them accordingly in iterations.
*/
function compare(a,b){
return a-b;
}
[Link]([Link](compare));

Output:
-120,0,5.2,20,30,100

Code for the above method is provided below:


Program 1:

// JavaScript to illustrate sort() function


function func() {
//Original string
var arr = [2, 5, 8, 1, 4]

//Sorting the array


[Link]([Link]());
[Link](arr);
}
func();

Output

[ 1, 2, 4, 5, 8 ]
[ 1, 2, 4, 5, 8 ]

Program 2:

// JavaScript to illustrate sort() function


function func() {

// Original array
var arr = [2, 5, 8, 1, 4];
[Link]([Link](function(a, b) {
return a + 2 * b;
}));
[Link](arr);
}
func();

Output

[ 2, 5, 8, 1, 4 ]
[ 2, 5, 8, 1, 4 ]

Time Complexity: The time complexity of the sort() method varies & depends on implementation.
For example, in the Firefox web browser, it uses the merge sort implementation which gives time
complexity as O(nlog n). Whereas, in Google Chrome web browser, it uses the Timsort implementation (a
hybrid of merge sort and insertion sort), gives time complexity is O(nlogn).

Split and Join

Introduction

The split and join methods in JavaScript are powerful tools for manipulating strings and arrays. The split method is
used to divide a string into an array of substrings, while the join method combines an array of elements into
a single string. These methods often work together to achieve various tasks, such as checking if a string is a
palindrome.

Split Method

The split method splits a string into an array of substrings based on a specified separator.

Syntax:
[Link](separator, limit)

separator: It is used to specify the character, or the regular expression, to use for splitting the string.
If the separator is unspecified then the entire string becomes one single array element. The same
also happens when the separator is not present in the string. If the separator is an empty string (“”)
then every character of the string is separated.
 limit: Defines the upper limit on the number of splits to be found in the given string. If the string
remains unchecked after the limit is reached then it is not reported in the array.
Return value: This function returns an array of strings that is formed after splitting the given string at each point
where the separator occurs.

Below is an example of the String split() Method.

Example:

// JavaScript Program to illustrate split() function

function func() {
//Original string
var str = 'Geeks for Geeks'
var array = [Link]("for");
[Link](array);
}
func();
Output

[ 'Geeks ', ' Geeks' ]

Examples of the above function are provided below:

Example 1:
var str = 'It iS a 5r&e@@t Day.'
var array = [Link](" ");
print(array);

Output: In this example, the function split() creates an array of strings by splitting str wherever ” ” occurs.
[It,iS,a,5r&e@@t,Day.]

Example 2:
var str = 'It iS a 5r&e@@t Day.'
var array = [Link](" ",2);
print(array);

Output: In this example, the function split() creates an array of strings by splitting str wherever ” ” occurs. The
second argument 2 limits the number of such splits to only 2.
[It,iS]

Codes for the above function are provided below:

Program 1:

function func() {
//Original string
var str = 'It iS a 5r&e@@t Day.'
var array = [Link](" ");
[Link](array);
}
func();

Output

[ 'It', 'iS', 'a', '5r&e@@t', 'Day.' ]

Program 2:
function func() {

// Original string
var str = 'It iS a 5r&e@@t Day.'

// Splitting up to 2 terms
var array = [Link](" ",2);
[Link](array);
}
func();

Output

[ 'It', 'iS' ]

Practical Example: Checking for Palindrome

A palindrome is a string that reads the same forward and backward. We can use split, reverse, and join to check if
a string is a palindrome.

function isPalindrome(inputString) {
let arr = [Link]("");
let reversedArr = [Link]();
let reversedString = [Link]("");
return inputString === reversedString;
}

let inputString = "madam";


[Link](isPalindrome(inputString)); // true

inputString = "hello";
[Link](isPalindrome(inputString)); // false

Detailed Steps

1. Split the string into an array of characters:


let inputString = "madam";
let arr = [Link]("");
[Link](arr); // ["m", "a", "d", "a", "m"]

2.
2. Reverse the array:

3.
let reversedArr = [Link]();
[Link](reversedArr); // ["m", "a", "d", "a", "m"]
4.
3. Join the array back into a string:

5.
let reversedString = [Link]("");
[Link](reversedString); // "madam"

6.
4. Compare the original string with the reversed string:

7.
if (inputString === reversedString) {
[Link]("The string is a palindrome.");
} else {
[Link]("The string is not a palindrome.");
}

8.
Array join() Method

The [Link]() method is used to join the elements of an array into a string. The elements of the string will be
separated by a specified separator and its default value is a comma(, ).

Syntax:
[Link](separator)

Parameters: This method accepts single parameter as mentioned above and described below:

separator: It is Optional i.e, it can be either used as parameter or not. Its default value is comma(, ).
Return Value: It returns the string which contain the collection of array's elements.

Below example illustrate the Array join() method in JavaScript:

 Example 1: In this example the function join() joins together the elements of the array into a string
using ‘|’.
var a = [1, 2, 3, 4, 5, 6];
print([Link]('|'));

Output:
1|2|3|4|5|6

 Example 2: In this example the function join() joins together the elements of the array into a string
using ‘, ‘ since it is the default value.
var a = [1, 2, 3, 4, 5, 6];
print([Link]());

Output:
1, 2, 3, 4, 5, 6

 Example 3: In this example the function join() joins together the elements of the array into a string
using ‘ ‘ (empty string).
var a = [1, 2, 3, 4, 5, 6];
print([Link](''));

Output:
123456

Code for the above method is provided below:

Program 1:

function func() {
var a = [ 1, 2, 3, 4, 5, 6 ];
[Link]([Link]());
}
func();

Output

1,2,3,4,5,6

Program 2:

function func() {
var a = [ 1, 2, 3, 4, 5, 6 ];
[Link]([Link](''));
}
func();

Output

123456

Use Cases for Split and Join

 Reversing a String: As demonstrated above, split a string into characters, reverse the array, and join
it back into a string.
 Transforming Data: For example, converting a CSV string into an array and back.
 String Manipulation: Easily modify parts of a string by splitting it into an array, altering the array, and
joining it back into a string.

Conclusion
The split and join methods are essential for string and array manipulation in JavaScript. By understanding how to
use these methods together, you can efficiently perform a variety of tasks, such as checking for palindromes,
transforming data formats, and more. Keep practicing these methods to gain confidence and proficiency in
handling strings and arrays in JavaScript.

Spread operator

The spread operator in JavaScript is a powerful feature that allows you to unpack elements from arrays or
properties from objects. It is represented by three dots ( ...) and can be used in various contexts to achieve
different outcomes. Let's delve into how the spread operator works, particularly with arrays.

Spreading an Array
The spread operator can be used to spread the elements of an array into another array or to perform operations
that require unpacking of array elements.

Syntax:
var variablename1 = [...value];

In the above syntax, … is spread operator which will target all values in particular variable. When … occurs in
function call or alike, it is called a spread operator. Spread operator can be used in many cases, like when we
want to expand, copy, concat with math object. Let’s look at each of them one by one:

Note: In order to run the code in this article make use of the console provided by the browser.

Basic Usage

Let's start with a simple example:

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


[Link](...arr);

Output

12345

In this example, the array arr is unpacked, and each element is printed individually.

Using Spread Operator to Merge Arrays


One of the common use cases of the spread operator is to merge multiple arrays.

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


const arr2 = [6, 7, 8, 9];
const mergedArr = [...arr1, ...arr2];
[Link](mergedArr); // Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Output

[
1, 2, 3, 4, 5,
6, 7, 8, 9
]

In this example, arr1 and arr2 are merged into a new array mergedArr using the spread operator. This does not
mutate the original arrays.

Adding Elements While Merging

You can also add elements in between or around the arrays while merging.

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


const arr2 = [8, 9];
const combinedArr = [...arr1, 6, 7, ...arr2, 10, 11];
[Link](combinedArr); // Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Output

[
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11
]

In this example, 6 and 7 are added between arr1 and arr2, and 10 and 11 are added at the end.

Preventing Mutation
One of the key advantages of using the spread operator is that it prevents mutation of the original arrays. This is
especially important in functional programming and when dealing with state in applications like React.
const arr1 = [1, 2, 3, 4, 5];
const arr3 = [...arr1, 6, 7];
[Link](arr1); // Output: [1, 2, 3, 4, 5]
[Link](arr3); // Output: [1, 2, 3, 4, 5, 6, 7]

Output

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

In this example, arr1 remains unchanged after creating arr3, which includes additional elements.

Spread Operator in Objects


The spread operator can also be used with objects to copy or merge them.

Copying an Object

const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1 };
[Link](obj2); // Output: { a: 1, b: 2 }

Output

{ a: 1, b: 2 }

Here, obj2 is a shallow copy of obj1.

Merging Objects

const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObj = { ...obj1, ...obj2 };
[Link](mergedObj); // Output: { a: 1, b: 2, c: 3, d: 4 }

Output
[ 'a', 'b', 'c' ]
[ 'a', 'b', 'c', 'd' ]
[ 'a', 'b', 'c' ]

In this example, obj1 and obj2 are merged into a new object mergedObj.

Updating Properties

const obj1 = { a: 1, b: 2 };
const updatedObj = { ...obj1, b: 3 };
[Link](updatedObj); // Output: { a: 1, b: 3 }

Output

{ a: 1, b: 3 }

Even though we get the content on one array inside the other one, but actually it is array inside another array
which is definitely what we did not want. If we want the content to be inside a single array we can make use
of the spread operator.

// expand using spread operator

let arr = ['a','b'];


let arr2 = [...arr,'c','d'];

[Link](arr2); // [ 'a', 'b', 'c', 'd' ]

Output

[ 'a', 'b', 'c', 'd' ]

Math

The Math object in JavaScript has different properties that we can make use of to do what we want like finding
the minimum from a list of numbers, finding maximum etc. Consider the case that we want to find the
minimum from a list of numbers, we will write the following code:

[Link]([Link](1,2,3,-1)); //-1
Output

-1

Now consider that we have an array instead of a list, this above Math object method would not work and will
return NaN, like:

// min in an array using [Link]()


let arr = [1,2,3,-1];
[Link]([Link](arr)); //NaN

Output

NaN

When …arr is used in the function call, it “expands” an iterable object arr into the list of arguments.
In order to avoid this NaN output, we make use of spread operator, like:

// with spread
let arr = [1,2,3,-1];

[Link]([Link](...arr)); //-1

Output

-1

Example of spread operator with objects

ES6 has added spread property to object literals in JavaScript. The spread operator (…) with objects is used to
create copies of existing objects with new or updated values or to make a copy of an object with more
properties. Let’s take at an example of how to use the spread operator on an object,

const user1 = {
name: 'Jen',
age: 22
};

const clonedUser = { ...user1 };


[Link](clonedUser);

Output

{ name: 'Jen', age: 22 }

Here we are spreading the user1 object. All key-value pairs of the user1 object are copied into the clonedUser
object. Let’s look on another example of merging two objects using the spread operator,

const user1 = {
name: 'Jen',
age: 22,
};

const user2 = {
name: "Andrew",
location: "Philadelphia"
};

const mergedUsers = {...user1, ...user2};


[Link](mergedUsers)

Output

{ name: 'Andrew', age: 22, location: 'Philadelphia' }

mergedUsers is a copy of user1 and user2. Actually, every enumerable property on the objects will be copied to
mergedUsers object. The spread operator is just a shorthand for the [Link]() method but, they are
some differences between the two.

Here, the property b in obj1 is updated to 3 in updatedObj.

Summary
The spread operator is a versatile tool in JavaScript that helps in copying, merging, and adding elements or
properties without mutating the original data structures. This is crucial for maintaining immutability and
ensuring that the original arrays or objects remain unchanged.

Destructuring Array

The Destructuring assignment is the important technique introduced in ECMAScript 2015 (ES6) version of
JavaScript that provides a shorthand syntax to extract or unpack array elements or properties of an object
into distinct variables using a single line of code. In other words, this assignment helps us to segregate data
of any iterable as well as non-iterable object and then helps us to use that segregated data individually on
need or demand. It makes the code shorter and more readable.

In general way implementation of the extraction of the array is as shown below:

Example:

var names = ["alpha", "beta", "gamma", "delta"];

var firstName = names[0];


var secondName = names[1];

[Link](firstName);//"alpha"
[Link](secondName);//"beta"

Output

alpha
beta

Syntax:

 Array destructuring:
var x, y;
[x, y] = [10, 20];
[Link](x); // 10
[Link](y); // 20

 or
[x, y, ...restof] = [10, 20, 30, 40, 50];
[Link](x); // 10
[Link](y); // 20
[Link](restof); // [30, 40, 50]

 Object destructuring:
({ x, y} = { x: 10, y: 20 });
[Link](x); // 10
[Link](y); // 20

 or
({x, y, ...restof} = {x: 10, y: 20, m: 30, n: 40});
[Link](x); // 10
[Link](y); // 20
[Link](restof); // {m: 30, n: 40}

Array destructuring: Using the Destructuring Assignment in JavaScript array possible situations, all the examples
are listed below:
 Example 1: When using destructuring assignment the same extraction can be done using below
implementations.

var names = ["alpha", "beta", "gamma", "delta"];


var [firstName, secondName] = names;

[Link](firstName);//"alpha"
[Link](secondName);//"beta"

//Both of the procedure are same


var [firstName, secondName] = ["alpha", "beta", "gamma", "delta"];

[Link](firstName);//"alpha"
[Link](secondName);//"beta

Output

alpha
beta
alpha
beta

 Example 2: The array elements can be skipped as well using a comma separator. A single comma can
be used to skip a single array element. One key difference between the spread operator and array
destructuring is that the spread operator unpacks all array elements into a comma-separated list
which does not allow us to pick or choose which elements we want to assign to variables. To skip the
whole array it can be done using the number of commas as there is a number of array elements.

var [firstName,,thirdName] = ["alpha", "beta", "gamma", "delta"];

[Link](firstName);//"alpha"
[Link](thirdName);//"gamma"

Output

alpha
gamma

 Example 3: In order to assign some array elements to variable and rest of the array elements to only
a single variable can be achieved by using rest operator (…) as in below implementation. But one
limitation of rest operator is that it works correctly only with the last elements implying a subarray
cannot be obtained leaving the last element in the array.

var [firstName,,...lastName] = ["alpha", "beta", "gamma", "delta"];

[Link](firstName);//"alpha"
[Link](lastName);//"gamma, delta"

Output

alpha
[ 'gamma', 'delta' ]

 Example 4: Values can also be swapped using destructuring assignment as below:

var names = ["alpha", "beta", "gamma", "delta"];


var [firstName, secondName] = names;
[Link](firstName);//"alpha"
[Link](secondName);//"beta"

//After swapping
[firstName, secondName] = [secondName, firstName]

[Link](firstName);//"beta"
[Link](secondName);//"alpha"

Output

alpha
beta
beta
alpha

 Example 5: Data can also be extracted from an array that is returned from a function. One advantage
of using a destructuring assignment is that there is no need to manipulate an entire object in a
function but just the fields that are required can be copied inside the function.

function NamesList() {
return ["alpha", "beta", "gamma", "delta"]
}
var[firstName, secondName] = NamesList();

[Link](firstName);//"alpha"
[Link](secondName);//"beta"

Output

alpha
beta

Destructuring Objects

Destructuring objects is particularly useful when you need to extract specific properties from an object.

Basic Object Destructuring

 Example 6: In ES5 to assign variables from objects its implementation is

const user = {
name: 'John Doe',
age: 30,
job: 'Developer'
};
const { name, age, job } = user;
[Link](name); // John Doe
[Link](age); // 30
[Link](job); // Developer

Output

John Doe
30
Developer

Renaming Variables

You can rename variables while destructuring.

Example 7:

const user = {
name: 'John Doe',
age: 30,
job: 'Developer'
};
const { name: userName, age: userAge, job: userJob } = user;
[Link](userName); // John Doe
[Link](userAge); // 30
[Link](userJob); // Developer

Output

John Doe
30
Developer

Nested Destructuring

You can destructure nested objects.

Example 8:

const user = {
name: 'John Doe',
address: {
city: 'New York',
country: 'USA'
}
};
const { name, address: { city, country } } = user;
[Link](name); // John Doe
[Link](city); // New York
[Link](country); // USA

Default Values

You can set default values while destructuring.

Example 9:

const user = {
name: 'John Doe',
age: 30
};
const { name, job = 'Unemployed' } = user;
[Link](name); // John Doe
[Link](job); // Unemployed

Destructuring Function Parameters


Destructuring can be used in function parameters to directly extract values from objects passed to the function.

Example 10:

function displayUser({ name, age }) {


[Link](`Name: ${name}, Age: ${age}`);
}

const user = {
name: 'John Doe',
age: 30
};

displayUser(user); // Name: John Doe, Age: 30

Conclusion
Destructuring is a convenient way to extract values from arrays and objects. It makes the code more readable
and reduces the need for multiple lines of variable assignments. Practice using destructuring in various
scenarios to get comfortable with this powerful feature in JavaScript.

Copy By Reference

In JavaScript, working with arrays and objects often involves copying or cloning them. However, there's a
common pitfall related to shallow copying, where changes to one array can unexpectedly affect another.
Let's delve into this concept and see how to properly handle array copying to avoid such issues.

The Problem with Shallow Copying


Example of Shallow Copying

Consider the following example where we create a copy of an array and then modify the copy

let arr1 = [1, 2, 3];


let arr2 = arr1; // Shallow copy

[Link]('ARR1:', arr1); // Output: [1, 2, 3]


[Link]('ARR2:', arr2); // Output: [1, 2, 3]

// Modify arr2
[Link](4);

[Link]('Updated ARR2:', arr2); // Output: [1, 2, 3, 4]


[Link]('Updated ARR1:', arr1); // Output: [1, 2, 3, 4]

Output

ARR1: [ 1, 2, 3 ]
ARR2: [ 1, 2, 3 ]
Updated ARR2: [ 1, 2, 3, 4 ]
Updated ARR1: [ 1, 2, 3, 4 ]

Explanation

When you assign arr1 to arr2, both variables reference the same array in memory. Therefore, any changes
to arr2 also affect arr1. This is due to the nature of objects and arrays in JavaScript being reference types.

Solutions to Properly Copy Arrays


1. Using the Spread Operator

The spread operator (...) is a convenient way to create a shallow copy of an array that points to a different
memory location.

Syntax:

var variablename1 = [...value];

// spread operator for copying


let arr = ['a','b','c'];
let arr2 = [...arr];

[Link](arr); // [ 'a', 'b', 'c' ]

[Link]('d'); //inserting an element at the end of arr2

[Link](arr2); // [ 'a', 'b', 'c', 'd' ]


[Link](arr); // [ 'a', 'b', 'c' ]
Output

[ 'a', 'b', 'c' ]


[ 'a', 'b', 'c', 'd' ]
[ 'a', 'b', 'c' ]

2. Using a for Loop

Another way to create a copy is by manually iterating over the array and pushing elements to the new array.

let arr4 = [1, 2, 3];


let arr5 = [];

for (let number of arr4) {


[Link](number);
}

[Link]('ARR4:', arr4); // Output: [1, 2, 3]


[Link]('ARR5:', arr5); // Output: [1, 2, 3]

// Modify arr5
[Link](4);

[Link]('Updated ARR5:', arr5); // Output: [1, 2, 3, 4]


[Link]('Updated ARR4:', arr4); // Output: [1, 2, 3]

Output

ARR4: [ 1, 2, 3 ]
ARR5: [ 1, 2, 3 ]
Updated ARR5: [ 1, 2, 3, 4 ]
Updated ARR4: [ 1, 2, 3 ]

3. Using [Link]

The [Link] method can also be used to create a shallow copy of an array.

let arr6 = [1, 2, 3];


let arr7 = [Link](arr6); // Properly copying the array using [Link]

[Link]('ARR6:', arr6); // Output: [1, 2, 3]


[Link]('ARR7:', arr7); // Output: [1, 2, 3]
// Modify arr7
[Link](4);

[Link]('Updated ARR7:', arr7); // Output: [1, 2, 3, 4]


[Link]('Updated ARR6:', arr6); // Output: [1, 2, 3]

4. Using concat

The concat method can be used to create a new array that includes the elements of the original array.

let arr8 = [1, 2, 3];


let arr9 = [Link](); // Properly copying the array using concat

[Link]('ARR8:', arr8); // Output: [1, 2, 3]


[Link]('ARR9:', arr9); // Output: [1, 2, 3]

// Modify arr9
[Link](4);

[Link]('Updated ARR9:', arr9); // Output: [1, 2, 3, 4]


[Link]('Updated ARR8:', arr8); // Output: [1, 2, 3]

Output

ARR8: [ 1, 2, 3 ]
ARR9: [ 1, 2, 3 ]
Updated ARR9: [ 1, 2, 3, 4 ]
Updated ARR8: [ 1, 2, 3 ]

Summary
 Shallow Copy: A shallow copy refers to creating a copy of an array or object where the copy still
points to the same memory location as the original. Changes to the copy will reflect in the original.
 Deep Copy: A deep copy involves creating a completely independent copy of the array or object,
such that changes to the copy do not affect the original. For arrays and objects containing only
primitive types, methods like the spread operator, [Link], and concat work well.

Object and its Properties


Objects are fundamental in JavaScript, providing a versatile way to store and manipulate data. They are
especially useful when working with data fetched from APIs, which is often structured as objects. This lesson
covers the basics of creating, accessing, and working with objects in JavaScript.

Creating Objects
An object literal is one of the simplest and most common ways to create an object in JavaScript.

Syntax:
let object_name = {
key_name : value,
...
}

Let us look at an example of a JavaScript Object below :

const person = {
name: 'Prakash',
age: 99,
job: 'Mentor'
};

Here, we have created an object person with three properties: name, age, and job.

Accessing Object Properties

There are two primary ways to access properties of an object:

1. Dot Notation:

[Link]([Link]); // Output: Prakash


[Link]([Link]); // Output: 99

[Link] Notation:

[Link](person['name']); // Output: Prakash


[Link](person['age']); // Output: 99

Bracket notation is particularly useful when property names contain spaces or are dynamic.
Adding and Modifying Properties

You can add new properties or modify existing ones using either dot notation or bracket notation.

[Link] = 'New York'; // Adding a new property


[Link] = 100; // Modifying an existing property
[Link]([Link]); // Output: New York
[Link]([Link]); // Output: 100

Deleting Properties

To remove a property from an object, use the delete operator.

delete [Link];
[Link]([Link]); // Output: undefined

Nested Objects
Objects can contain other objects, creating a nested structure.

const user = {
name: 'John',
address: {
street: '123 Main St',
city: 'Anytown',
country: 'USA'
}
};
[Link]([Link]); // Output: Anytown

Object Methods
Objects can also contain functions, known as methods.

const car = {
make: 'Tesla',
model: 'Model S',
start: function() {
[Link]('Car started');
}
};
[Link](); // Output: Car started

Working with Dynamic Properties


Sometimes, you need to work with properties dynamically, particularly when property names are determined at
runtime.

const propName = 'make';


[Link](car[propName]); // Output: Tesla

Handling Multi-Word Property Names


Properties with multi-word names need to be accessed using bracket notation.

const userProfile = {
'first name': 'Jane',
'last name': 'Doe'
};
[Link](userProfile['first name']); // Output: Jane

Creating a Shallow Copy of an Object


To create a shallow copy of an object, use the spread operator.

const userCopy = { ...user };


[Link](userCopy); // Output: { name: 'John', address: { street: '123 Main St', city: 'Anytown', country: 'USA' } }

Summary
 Objects store data as key-value pairs, with each key being a string (or implicitly converted to a
string).
 Properties can be accessed and modified using dot or bracket notation.
 Objects can contain other objects and functions.
 The spread operator creates a shallow copy of an object.

Functions as Property
In JavaScript, functions can be used as properties of objects. This can be a powerful tool for organizing and
encapsulating functionality within an object, making it easier to maintain and reuse code.

To better understand this concept, let's dive into some code examples and interact with them.

Using Functions as Object Properties


Creating an Object with a Function Property

You can add a function as a property to an object. This function can then be called like any other property of the
object.

const obj = {
name: 'Prakash Sakari',
greetMessage: function() {
[Link]('Hello, Prakash! Welcome to GFG.');
}
};

// Calling the function property


[Link](); // Output: Hello, Prakash! Welcome to GFG.
In the example above, greetMessage is a key with a function as its value. This is an anonymous function assigned
to the greetMessage property.

Using Method Shorthand

JavaScript provides a shorthand method to define functions within objects.

const obj = {
name: 'Prakash Sakari',
greetMessage() {
[Link]('Hello, Prakash! Welcome to GFG.');
}
};

// Calling the function property


[Link](); // Output: Hello, Prakash! Welcome to GFG.
This method shorthand is more concise and avoids the need for the function keyword.

Accessing Functions in Objects

When you want to call a function within an object, you use the dot notation followed by parentheses.
[Link](); // Output: Hello, Prakash! Welcome to GFG.
Example with Multiple Properties and Methods

Let's create a more complex object with multiple properties and methods.

const person = {
name: 'Prakash Sakari',
age: 99,
job: 'Mentor',
courses: ['HTML', 'CSS', 'JavaScript', 'ReactJS', 'Python'],
greet() {
[Link](`Hello, ${[Link]}! Welcome to your job as a ${[Link]}.`);
},
displayCourses() {
[Link](`${[Link]} teaches the following courses:`);
[Link](course => [Link](course));
}
};

// Calling the methods


[Link](); // Output: Hello, Prakash Sakari! Welcome to your job as a Mentor.
[Link](); // Output: Prakash Sakari teaches the following courses: HTML, CSS, JavaScript, ReactJS, Python

Output

Hello, Prakash Sakari! Welcome to your job as a Mentor.


Prakash Sakari teaches the following courses:
HTML
CSS
JavaScript
ReactJS
Python

In this example, person has two methods: greet and displayCourses. These methods can access other properties of
the object using this.

Function Borrowing

Function borrowing allows one object to borrow methods from another object. This is especially useful when
multiple objects need to use the same method.

Here, we define an object person with properties name and age, as well as a function property sayHello. This
function uses the this keyword to reference the name property of the object it is called on.
const person1 = {
name: 'John',
greet() {
[Link](`Hello, ${[Link]}!`);
}
};

const person2 = {
name: 'Jane'
};

// Borrowing the greet method from person1


[Link] = [Link];

[Link](); // Output: Hello, John!


[Link](); // Output: Hello, Jane!

Output

Hello, John!
Hello, Jane!

Key Points

1. Functions as Properties: Functions can be used as properties in objects, providing methods to the
object.
2. Method Shorthand: JavaScript allows shorthand syntax for methods in objects.
3. Accessing Functions: Functions in objects are accessed using dot notation followed by parentheses.
4. Function Borrowing: Objects can borrow methods from other objects, allowing code reuse and
flexibility.

Summary

Understanding how to use functions within objects is crucial for creating dynamic and flexible code. By
incorporating methods into your objects, you can create powerful abstractions and reuse code efficiently.
This lesson covers the basics, but as you work on more complex applications, you'll see just how versatile
and useful these techniques can be. In the next lesson, we'll explore adding properties to objects
dynamically and using computed properties.

Computed Properties
In this Article, we will learn how to add properties to an existing object and understand the concept of computed
properties.

Adding Properties to an Existing Object


To add a new property to an existing object, you can use either dot notation or bracket notation.

Using Dot Notation

Here's how you can add properties using dot notation:

const obj = {
name: 'Prakash',
age: 100
};

// Adding new properties using dot notation


[Link] = 'Mumbai';
[Link] = 'Maharashtra';

[Link](obj);
// Output: { name: 'Prakash', age: 100, city: 'Mumbai', state: 'Maharashtra' }

Output

My fullname is: somya jain

Using Bracket Notation

Bracket notation is useful when the property name is dynamic or not a valid identifier:
objectname["name of the property name"]=value

const obj = {
name: 'Prakash',
age: 100
};

// Adding new properties using bracket notation


obj['city'] = 'Mumbai';
obj['state'] = 'Maharashtra';

[Link](obj);
// Output: { name: 'Prakash', age: 100, city: 'Mumbai', state: 'Maharashtra' }
Output

My fullname is: somya jain

Computed Properties
Computed properties allow you to dynamically set property names. This is particularly useful when you want to
add a property to an object based on a variable value.

Example of Computed Properties

Let's take an example where you get a key from the user and add that key to the object:

const readlineSync = require('readline-sync');

const obj = {
name: 'Prakash',
age: 100
};

// Getting a key from the user


const key = [Link]('What do you want to know about the mentor? (name, age, city, state): ');

// Adding the key to the object dynamically


obj[key] = obj[key] || 'Not Available';

[Link](obj);
When you run this code, it will prompt you to enter a property name. If the property exists, it will show the
value; otherwise, it will add a new property with the value 'Not Available'.

Example of Adding Computed Property Dynamically

You can also add a property dynamically based on user input:

const readlineSync = require('readline-sync');

const obj = {
name: 'Prakash',
age: 100
};

const course = [Link]('Which course do you want to learn? (HTML, CSS, JS, React, Redux): ');

// Adding a computed property to the object


obj[course] = 'Course not available';
[Link](obj);
When you run this code, it will prompt you to enter a course name, and it will add that course name as a
property to the object with the value 'Course not available'.

Key Points

1. Adding Properties: You can add properties to an existing object using dot notation or bracket
notation.
2. Computed Properties: Use computed properties to dynamically add properties to an object based on
variable values.
3. Bracket Notation: Use bracket notation when dealing with dynamic property names or when the
property name is not a valid identifier.

Summary

In this lesson, we've covered how to add properties to an existing object and how to use computed properties to
dynamically set property names. These techniques are essential for working with objects in JavaScript and
provide a flexible way to manage object properties.

Property Shorthand

In this Article, we will explore the concept of shorthand properties in JavaScript objects. Shorthand properties
are a syntactic feature that allows you to create objects more concisely when the property names and
variable names are the same.

What are Shorthand Properties?


Shorthand properties simplify the syntax for defining object properties when the property name is the same as
the variable name holding the value. Instead of writing both the property and its value explicitly, you can use
shorthand syntax.

Example of Shorthand Properties

Consider a function that takes two parameters and returns an object:

function getObject(name, city) {


return {
name: name,
city: city
};
}

const obj = getObject('Akash', 'Mumbai');


[Link](obj); // Output: { name: 'Akash', city: 'Mumbai' }

Output

{ name: 'Raj', age: 20, location: 'India' }

In the example above, we explicitly write the property names ( name and city) and their values
(name and city variables).

Using shorthand properties, we can simplify this as:

function getObject(name, city) {


return {
name,
city
};
}

const obj = getObject('Akash', 'Mumbai');


[Link](obj); // Output: { name: 'Akash', city: 'Mumbai' }

Output

{ name: 'Raj', age: 20, location: 'India' }

Here, name and city are shorthand for name: name and city: city.

Additional Examples with Shorthand Properties


Creating an Object with Multiple Properties

Let's define some variables and use them to create an object using shorthand properties:

const age = 25;


const job = 'Developer';
const student = 'Ashish';
const course = 'Redux';
// Using shorthand properties
const person = {
age,
job
};

[Link](person); // Output: { age: 25, job: 'Developer' }

// Logging student and course as an object


[Link]({ student, course }); // Output: { student: 'Ashish', course: 'Redux' }

Using Shorthand Properties in a Function

Let's create a function that generates an object with shorthand properties:

function createStudent(name, city) {


return {
name,
city
};
}

const student1 = createStudent('Akash', 'Mumbai');


const student2 = createStudent('Ashish', 'Chennai');

[Link](student1); // Output: { name: 'Akash', city: 'Mumbai' }


[Link](student2); // Output: { name: 'Ashish', city: 'Chennai' }

Practical Example

Let's create a practical example where we define a list of students and their respective courses using shorthand
properties:

const students = [
{ name: 'Akash', city: 'Mumbai', course: 'JavaScript' },
{ name: 'Ashish', city: 'Chennai', course: 'Redux' },
{ name: 'Sita', city: 'Delhi', course: 'React' }
];

[Link](student => {
[Link](student);
});

Summary
Shorthand properties are a useful feature in JavaScript that can make your code more concise and readable,
especially when creating objects with properties that have the same names as variables.
Key Points:

1. Shorthand Properties: Use shorthand properties when the property name and variable name are the
same.
2. Syntax: Instead of name: name, you can write name.
3. Use Cases: Useful in functions that return objects, logging multiple variables as objects, and more.

for- in Loop

In this Article, we'll delve deeper into JavaScript objects by exploring how to check for the existence of
properties using the in operator and how to loop through an object's properties using the for...in loop. These
techniques are fundamental for effectively working with objects in JavaScript.

The in Operator
The in operator is used to check if a specified property exists in an object. It returns true if the property is found
and false if it is not.

Example of the in Operator

const obj = {
name: 'Prakash',
city: 'Mumbai'
};

// Checking if 'name' property exists in obj


const isNameFound = 'name' in obj;
[Link](isNameFound); // Output: true

// Checking if 'age' property exists in obj


const isAgeFound = 'age' in obj;
[Link](isAgeFound); // Output: false

Output

true
false

In the example above, we use the in operator to check for the existence of the name and age properties in
the obj object.

Looping Through an Object with for...in


The for...in loop allows you to iterate over the enumerable properties of an object. During each iteration, the
loop assigns the current property name to a variable, which can then be used to access the property's value.

Example of for...in Loop

const person = {
name: 'Prakash',
city: 'Mumbai'
};

// Looping through the object


for (let key in person) {
[Link](`${key}: ${person[key]}`);
}

Output

name: Prakash
city: Mumbai

n this example, the for...in loop iterates over the properties of the person object, logging both the property
names and their values to the console.

Using for...in with Additional Information

We can enhance the previous example to show both keys and values in a formatted string.

const person = {
name: 'Prakash',
city: 'Mumbai'
};

// Looping through the object and displaying key-value pairs


for (let key in person) {
[Link](`Key: ${key}, Value: ${person[key]}`);
}

Output

Key: name, Value: Prakash


Key: city, Value: Mumbai

Summary
Using the in operator and the for...in loop, you can effectively work with objects in JavaScript. These tools allow
you to check for the existence of properties and iterate over an object's properties, providing a flexible way
to handle dynamic data structures.

Key Points:

1. in Operator: Checks for the existence of a property in an object.


2. for...in Loop: Iterates over the enumerable properties of an object, accessing both keys and values.

Example: Combining in Operator and for...in Loop

Let's combine these concepts in a single example.

const car = {
make: 'Tesla',
model: 'Model S',
year: 2020
};

// Check if a property exists


const isModelPresent = 'model' in car;
[Link](isModelPresent); // Output: true

// Loop through the object


for (let prop in car) {
[Link](`${prop}: ${car[prop]}`);
}

Output

true
make: Tesla
model: Model S
year: 2020

In this example, we first check if the model property exists in the car object. Then, we use the for...in loop to
iterate over all properties of the car object and log them.

Understanding these fundamental concepts will enable you to work more efficiently with JavaScript objects,
making your code more dynamic and powerful. In the next lesson, we'll explore more advanced features of
JavaScript objects, such as computed properties and dynamically adding properties.

Object Refrence and Deep Copy


Understanding how to copy objects in JavaScript is crucial, especially when dealing with complex data structures.
Objects in JavaScript are copied by reference, meaning that creating a direct copy of an object does not
create a new object but rather a reference to the original object. This is known as a shallow copy. To create
an entirely new object with no references to the original, you need a deep copy.

Shallow Copy
A shallow copy creates a new object but does not recursively copy nested objects. Instead, it copies references
to the original nested objects. Here's an example:

Example of Shallow Copy

const person1 = {
name: 'Prakash',
age: 101,
address: {
city: 'Mumbai',
state: 'Maharashtra'
}
};

const person2 = person1; // Shallow copy


[Link] = 'Ashish';

[Link]([Link]); // Output: Ashish


[Link]([Link]); // Output: Ashish

Output

Ashish
Ashish

In this example, changing the name property of person2 also changes the name property of person1 because both
variables reference the same object.

Deep Copy
A deep copy creates a new object and recursively copies all properties of the original object, ensuring that there
are no shared references between the original and the new object.
Methods to Create Deep Copy

1. Using JSON methods:

const person1 = {
name: 'Prakash',
age: 101,
address: {
city: 'Mumbai',
state: 'Maharashtra'
}
};

const person2 = [Link]([Link](person1)); // Deep copy


[Link] = 'Ashish';
[Link] = 'Sirsa';

[Link]([Link]); // Output: Prakash


[Link]([Link]); // Output: Ashish
[Link]([Link]); // Output: Mumbai
[Link]([Link]); // Output: Sirsa

Output

Prakash
Ashish
Mumbai
Sirsa

2. Using a custom deep copy function:

function deepCopy(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
const copy = [Link](obj) ? [] : {};
for (const key in obj) {
if ([Link](key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}

const person1 = {
name: 'Prakash',
age: 101,
address: {
city: 'Mumbai',
state: 'Maharashtra'
}
};

const person2 = deepCopy(person1); // Custom deep copy


[Link] = 'Ashish';
[Link] = 'Sirsa';

[Link]([Link]); // Output: Prakash


[Link]([Link]); // Output: Ashish
[Link]([Link]); // Output: Mumbai
[Link]([Link]); // Output: Sirsa

Output

Prakash
Ashish
Mumbai
Sirsa

[Link]
The [Link] method creates a shallow copy of an object. It is useful for copying objects that do not contain
nested objects.

Example of [Link]

const person1 = {
name: 'Prakash',
age: 101
};

const person2 = [Link]({}, person1); // Shallow copy


[Link] = 'Ashish';

[Link]([Link]); // Output: Prakash


[Link]([Link]); // Output: Ashish

Output

Prakash
Ashish

However, when using [Link] with nested objects, the nested objects are still copied by reference, leading
to unexpected behavior:

const person1 = {
name: 'Prakash',
age: 101,
address: {
city: 'Mumbai',
state: 'Maharashtra'
}
};

const person2 = [Link]({}, person1); // Shallow copy


[Link] = 'Ashish';
[Link] = 'Sirsa';

[Link]([Link]); // Output: Sirsa


[Link]([Link]); // Output: Sirsa

Output

Sirsa
Sirsa

Spread Operator
The spread operator (...) can also be used to create a shallow copy of an object:

Example of Spread Operator

const person1 = {
name: 'Prakash',
age: 101,
address: {
city: 'Mumbai',
state: 'Maharashtra'
}
};

const person2 = { ...person1 }; // Shallow copy


[Link] = 'Ashish';
[Link] = 'Sirsa';

[Link]([Link]); // Output: Prakash


[Link]([Link]); // Output: Ashish
[Link]([Link]); // Output: Sirsa
[Link]([Link]); // Output: Sirsa

Output

Prakash
Ashish
Sirsa
Sirsa

Again, for nested objects, the spread operator does not create a deep copy.

Summary
 Shallow Copy: A shallow copy duplicates the top-level properties but does not recursively copy
nested objects. Methods like [Link] and the spread operator (...) create shallow copies.
 Deep Copy: A deep copy duplicates all properties, including nested objects, ensuring that no
references are shared between the original and the copied object. Methods
like [Link]([Link](obj)) and custom recursive functions can create deep copies.

Optional Chaining

The optional chaining ‘?.’ is an error-proof way to access nested object properties, even if an intermediate
property doesn’t exist. It was recently introduced by ECMA International, Technical Committee 39 –
ECMAScript which was authored by Claude Pache, Gabriel Isenberg, Daniel Rosenwasser, Dustin Savery. It
works similar to Chaining ‘.’ except that it does not report the error, instead it returns a value which is
undefined. It also works with function call when we try to make a call to a method which may not exist.

Nested Objects
Consider an object user with properties name, address, and likes. The address property itself is an object
containing street and city:

const user = {
name: 'Prakash',
address: {
street: '123 Main St',
city: 'Mumbai'
},
likes: ['reading', 'traveling']
};

To access the city from the address, you can write:


[Link]([Link]); // Output: Mumbai

However, if the city property does not exist or the address is undefined, you will encounter issues:
[Link]([Link]); // Output: undefined
[Link]([Link]); // Output: undefined

The real problem arises when the address itself is not defined:

const userWithoutAddress = {
name: 'Prakash'
};

[Link]([Link]); // Error: Cannot read property 'city' of undefined

Optional Chaining
Optional chaining allows you to safely access nested properties. It uses the ?. syntax to check if a property exists
before trying to access it.

Example with Nested Properties

Using optional chaining, you can safely access city:


[Link](user?.address?.city); // Output: Mumbai
[Link](userWithoutAddress?.address?.city); // Output: undefined

Example with Functions

Optional chaining also works with functions:

const userWithFunction = {
name: 'Prakash',
getDisplayMessage: function() {
[Link]('Welcome, Prakash');
}
};

userWithFunction?.getDisplayMessage?.(); // Output: Welcome, Prakash

const userWithoutFunction = {
name: 'Prakash'
};
userWithoutFunction?.getDisplayMessage?.(); // No output, no error

Practical Use Case


Optional chaining is especially useful when dealing with data from APIs where some properties may be optional:

fetch('[Link]
.then(response => [Link]())
.then(data => {
[Link](data?.address?.city);
});

Exercise
Try to implement optional chaining using square brackets for computed properties.
const key = 'address';
[Link](user[key]?.city); // Output: Mumbai

Summary
 Optional Chaining: Uses ?. to safely access nested properties and methods.
 Avoids Errors: Prevents errors when properties do not exist.
 Usage: Useful for optional or nullable properties.

Key Points

1. Nested Properties: Use ?. to access nested properties safely.


2. Functions: Use ?.() to call functions safely.
3. Avoid Overuse: Only use optional chaining when necessary.

Destructuring Object

Destructuring is an important and frequently used concept in JavaScript, especially when dealing with complex
objects or arrays, such as those returned from API responses. It allows for the unpacking of values from
arrays or properties from objects into distinct variables. Let's delve into the concept and see how it can be
effectively used.
Destructuring Objects
Basic Destructuring

Consider an object with multiple properties:

const obj = {
name: 'Prakash',
address: {
street: '123 Main St',
city: 'Mumbai',
state: 'Maharashtra'
},
courses: ['JavaScript', 'React', '[Link]']
};
To extract the name, address, and courses properties, you can use object destructuring:

const { name, address, courses } = obj;


[Link](name); // Output: Prakash
[Link](address); // Output: { street: '123 Main St', city: 'Mumbai', state: 'Maharashtra' }
[Link](courses); // Output: ['JavaScript', 'React', '[Link]']

Nested Destructuring

To access nested properties directly:

const { address: { city, state } } = obj;


[Link](city); // Output: Mumbai
[Link](state); // Output: Maharashtra

Renaming Variables

You can rename the variables while destructuring:

const { name: userName, address: { city: userCity } } = obj;


[Link](userName); // Output: Prakash
[Link](userCity); // Output: Mumbai

Using Rest Operator


To gather remaining properties into a new object:

const { name, ...rest } = obj;


[Link](name); // Output: Prakash
[Link](rest); // Output: { address: { street: '123 Main St', city: 'Mumbai', state: 'Maharashtra' }, courses: ['JavaScript', 'React',
'[Link]'] }

Destructuring Arrays
Basic Array Destructuring

For arrays, destructuring assigns values based on their position:

const numbers = [1, 2, 3];


const [a, b, c] = numbers;
[Link](a); // Output: 1
[Link](b); // Output: 2
[Link](c); // Output: 3

Skipping Items

You can skip items using commas:

const [first, , third] = numbers;


[Link](first); // Output: 1
[Link](third); // Output: 3

Using Rest Operator

To gather remaining items into a new array:

const [first, ...rest] = numbers;


[Link](first); // Output: 1
[Link](rest); // Output: [2, 3]

Practical Example with Nested Objects


Consider an API response with deeply nested objects:
const employees = {
engineers: {
emp1: { id: 1, name: 'John Doe', occupation: 'Software Engineer' },
emp2: { id: 2, name: 'Jane Smith', occupation: 'Data Scientist' }
},
placement: {
emp3: { id: 3, name: 'Emily Jones', occupation: 'HR Manager' }
},
youtube: {
emp4: { id: 4, name: 'Chris Brown', occupation: 'Content Creator' }
}
};
To extract specific details, you can use nested destructuring:

const { engineers: { emp2: { name: engineerName, occupation: engineerOccupation } } } = employees;


[Link](engineerName); // Output: Jane Smith
[Link](engineerOccupation); // Output: Data Scientist

Destructuring with Dynamic Property Names

You can use computed property names when destructuring:

const propName = 'engineers';


const { [propName]: engineers } = employees;
[Link](engineers); // Output: { emp1: { id: 1, name: 'John Doe', occupation: 'Software Engineer' }, emp2: { id: 2, name: 'Jane
Smith', occupation: 'Data Scientist' } }

Exercises
To practice, create an object with nested properties and try to extract specific values using destructuring. For
example:

1. Create an object company with nested properties for different departments.


2. Extract specific employee details from each department.
3. Use renaming, rest operator, and nested destructuring to manipulate the object.

Summary
Destructuring is a powerful feature that allows you to write cleaner and more readable code by unpacking values
from arrays or objects into distinct variables. It is especially useful when dealing with complex data
structures, such as those returned from APIs. Practice destructuring with various objects and arrays to
become proficient in using this feature.
Keys, Values & entries

JavaScript provides several methods that make it easier to work with objects. Three of the most useful methods
are [Link](), [Link](), and [Link](). These methods allow you to extract and manipulate the
properties of an object in different ways.

Example Object
Let's start with a simple object:

const obj = {
name: 'Prakash',
age: 99,
city: 'Mumbai'
};

[Link]()

The [Link]() method returns an array of a given object's own enumerable property [key, value] pairs.

Example

const entries = [Link](obj);


[Link](entries);
// Output: [ [ 'name', 'Prakash' ], [ 'age', 99 ], [ 'city', 'Mumbai' ] ]
As you can see, [Link](obj) returns an array of arrays, where each inner array contains a key-value pair
from the object.

[Link]()

The [Link]() method returns an array of a given object's own enumerable property names, iterated in the
same order that a normal loop would.

Example

const keys = [Link](obj);


[Link](keys);
// Output: [ 'name', 'age', 'city' ]
[Link](obj) returns an array containing the keys of the object.

[Link]()

The [Link]() method returns an array of a given object's own enumerable property values, in the same
order as provided by a for...in loop.

Example

const values = [Link](obj);


[Link](values);
// Output: [ 'Prakash', 99, 'Mumbai' ]

[Link](obj) returns an array containing the values of the object.

Practical Use Cases


Summing Values

Suppose you have an object with numerical values, and you want to find the sum of these values. Here's how
you can do it:

const obj = {
x: 1,
y: 2,
z: 17
};

const values = [Link](obj);


const sum = [Link]((acc, val) => acc + val, 0);

[Link](sum); // Output: 20

Output

20

Checking for Property Existence

You can check if a property exists in an object using the in operator:

const obj = {
name: 'Prakash',
age: 99,
city: 'Mumbai'
};

const isPropertyFound = 'name' in obj;


[Link](isPropertyFound); // Output: true

const isAgePropertyFound = 'age' in obj;


[Link](isAgePropertyFound); // Output: true

const isCountryPropertyFound = 'country' in obj;


[Link](isCountryPropertyFound); // Output: false

Output

true
true
false

Iterating Over an Object

You can use a for...in loop to iterate over the keys of an object:

const obj = {
name: 'Prakash',
age: 99,
city: 'Mumbai'
};

for (let key in obj) {


[Link](`${key}: ${obj[key]}`);
}

// Output:
// name: Prakash
// age: 99
// city: Mumbai

Output

name: Prakash
age: 99
city: Mumbai
Summary
In this lesson, we've covered some of the most useful object methods in JavaScript:

 [Link](): Returns an array of [key, value] pairs.


 [Link](): Returns an array of the object's keys.
 [Link](): Returns an array of the object's values.
 in operator: Checks if a property exists in an object.
 for...in loop: Iterates over the keys of an object.

"this" keyword

In this article, we're going to dive into how the this keyword works in JavaScript. Unlike some other programming
languages, the this keyword in JavaScript can be a bit tricky because it behaves differently depending on the
context in which it is used. Let's break it down.

The this Keyword in Objects


The this keyword in JavaScript typically refers to the object that is executing the function. When a function is a
property of an object (also called a method), this inside that function refers to the object itself.

Example:

const obj = {
name: "Prakash",
displayMessage: function() {
[Link](this);
}
};

[Link](); // Logs the obj object


In this example, this inside the displayMessage function refers to the obj object. When you run the code, it logs
the obj object to the console.

Using this Inside Methods

If you want to access properties of the object within a method, you can use this:

const obj = {
name: "Prakash",
displayMessage: function() {
[Link]("Hello, " + [Link]);
}
};

[Link](); // Logs "Hello, Prakash"


Here, [Link] refers to the name property of the obj object.

this in Global Context


When this is used inside a regular function (not an object method), it usually refers to the global object, which
is window in browsers.

Example:

function showThis() {
[Link](this);
}

showThis(); // Logs the global object (window in browsers)


Even though showThis is a function, because it's not attached to any object, this refers to the global object.

Arrow Functions and this


Arrow functions are special because they don’t have their own this. Instead, they inherit this from the
surrounding scope.

Example:

const obj = {
name: "Prakash",
displayMessage: () => {
[Link]([Link]);
}
};

[Link](); // Logs undefined


In this example, [Link] is undefined because this in an arrow function refers to the surrounding (global) scope,
not the obj object.

Regular Functions vs. Arrow Functions

 Regular Functions: this refers to the object that calls the method.
 Arrow Functions: this is inherited from the surrounding scope.
this Inside Nested Functions
Sometimes, you might encounter nested functions. If you use this inside a nested function, it won't refer to the
outer function’s this by default. Instead, it will refer to the global object.

Example:

const obj = {
name: "Prakash",
showName: function() {
function display() {
[Link]([Link]);
}
display();
}
};

[Link](); // Logs undefined


In this case, this inside the display function refers to the global object, not obj.

Solution: Using self or that

A common workaround is to store this in a variable (often named self or that) that the inner function can access:

const obj = {
name: "Prakash",
showName: function() {
const self = this;
function display() {
[Link]([Link]);
}
display();
}
};

[Link](); // Logs "Prakash"


Here, self refers to obj, so [Link] correctly logs "Prakash".

Summary
 In Methods: this refers to the object executing the method.
 In Regular Functions: this refers to the global object (window in browsers).
 In Arrow Functions: this is inherited from the surrounding scope.
 In Nested Functions: this can refer to the global object unless explicitly bound to the outer context
using self.
Constructor " New "

In this Article, we'll explore the concept of constructor functions and the new keyword in JavaScript. Constructor
functions are essentially regular functions, but with two key differences:

1. They are named with a capital letter.


2. They can only be executed using the new keyword.

Creating a Constructor Function


Let's start by defining a constructor function:

function User(name, age) {


[Link] = name;
[Link] = age;
}

Using the new Keyword

To create an instance of the User constructor function, you use the new keyword. This keyword ensures that a
new object is created and that the function is executed with its this keyword set to that new object.
const user1 = new User('Prakash', 101);
[Link](user1); // Output: User { name: 'Prakash', age: 101 }

Without the new keyword, the function would not create a new object, and the this keyword would refer to the
global object (or be undefined in strict mode). Using new ensures that this refers to the newly created object.

Adding Properties with this

In the constructor function, properties are added to the object being created using the this keyword:

function User(name, age) {


[Link] = name;
[Link] = age;
}

const user1 = new User('Prakash', 101);


const user2 = new User('Ashish', 25);

[Link]([Link]); // Output: Prakash


[Link]([Link]); // Output: 25
Output

Prakash
25

const user1 = new User('Prakash', 101);


const user2 = new User('Ashish', 25);
const user3 = new User('Ria', 99);
const user4 = new User('Sagar', 100);

[Link](user1); // Output: User { name: 'Prakash', age: 101 }


[Link](user2); // Output: User { name: 'Ashish', age: 25 }
[Link](user3); // Output: User { name: 'Ria', age: 99 }
[Link](user4); // Output: User { name: 'Sagar', age: 100 }

Creating Multiple Objects

You can use the constructor function to create multiple objects efficiently:

const user1 = new User('Prakash', 101);


const user2 = new User('Ashish', 25);
const user3 = new User('Ria', 99);
const user4 = new User('Sagar', 100);

[Link](user1); // Output: User { name: 'Prakash', age: 101 }


[Link](user2); // Output: User { name: 'Ashish', age: 25 }
[Link](user3); // Output: User { name: 'Ria', age: 99 }
[Link](user4); // Output: User { name: 'Sagar', age: 100 }

Output

User { name: 'Prakash', age: 27 }


User { name: 'Ashish', age: 25 }
User { name: 'Sadaf', age: 25 }
User { name: 'Rohan', age: 28 }

The this Keyword in Constructor Functions

The this keyword inside a constructor function refers to the newly created object. This is why we use this to
assign properties to the object.
Example

Let's log the value of this inside the constructor function to see what it refers to:

function User(name, age) {


[Link] = name;
[Link] = age;
[Link](this);
}

const user1 = new User('Prakash', 101);


// Output: User { name: 'Prakash', age: 101 }
As you can see, this refers to the new object created by the new keyword.

Summary
 Constructor Functions: Special functions used to create and initialize objects.
 new Keyword: Creates a new object and sets the this keyword in the constructor function to that new
object.
 Adding Properties: Use the this keyword to add properties to the object within the constructor
function.
By using constructor functions and the new keyword, you can efficiently create multiple objects with similar
properties and methods, making your code more modular and maintainable.

Function Borrowing - call and apply

In this Article, we'll discuss the concept of function borrowing in JavaScript using the call and apply methods.
Function borrowing allows one object to borrow methods from another object without making a copy of
that method. This is particularly useful to avoid code repetition and make the code more modular and
maintainable.

Understanding Function Borrowing


Suppose we have three objects representing users, each with a name and age property, and a sayHi method to
display their name. Instead of defining the sayHi method for each object, we can define it once and let the
objects borrow this method.

Initial Setup

const user1 = {
name: 'Prakash',
age: 25,
};

const user2 = {
name: 'Ashish',
age: 30,
};

const user3 = {
name: 'Suresh',
age: 35,
};

function sayHi() {
[Link]([Link]);
}

Now, let's say we want to borrow the greet method from person1 and use it on person2. We can do this using
the call() or apply() methods.

TUsing Call

The call method allows us to borrow a function and execute it with a specified this value and arguments. Here's
how it works:
[Link](user1); // Output: Prakash
[Link](user2); // Output: Ashish
[Link](user3); // Output: Suresh

The call method immediately invokes the function with the this value set to the specified object.

Using Apply

The apply method works similarly to call, but it takes an array of arguments instead of individual arguments. This
can be particularly useful when you have an array of arguments to pass.

function introduce(degree, year) {


[Link](`${[Link]}, Degree: ${degree}, Year: ${year}`);
}

[Link](user1, ['[Link] ECE', 2015]); // Output: Prakash, Degree: [Link] ECE, Year: 2015
[Link](user2, ['[Link] CS', 2018]); // Output: Ashish, Degree: [Link] CS, Year: 2018

Example of Function Borrowing

Let's look at a complete example to see how function borrowing can help us avoid repetition and keep the code
clean.
const user1 = {
name: 'Prakash',
age: 25,
};

const user2 = {
name: 'Ashish',
age: 30,
};

const user3 = {
name: 'Suresh',
age: 35,
};

function sayHi() {
[Link](`Hi, my name is ${[Link]}.`);
}

// Borrowing the sayHi function


[Link](user1); // Output: Hi, my name is Prakash.
[Link](user2); // Output: Hi, my name is Ashish.
[Link](user3); // Output: Hi, my name is Suresh.

// Using apply with arguments


function introduce(degree, year) {
[Link](`${[Link]}, Degree: ${degree}, Year: ${year}`);
}

[Link](user1, ['[Link] ECE', 2015]); // Output: Prakash, Degree: [Link] ECE, Year: 2015
[Link](user2, ['[Link] CS', 2018]); // Output: Ashish, Degree: [Link] CS, Year: 2018

Summary

 Call: Immediately invokes the function with a specified this value and arguments.
 Apply: Immediately invokes the function with a specified this value and arguments passed as an
array.

Function Borrowing - bind

In this Article, we'll discuss the concept of function borrowing in JavaScript using the bind method. Function
borrowing allows one object to borrow methods from another object without making a copy of that
method. This is particularly useful to avoid code repetition and make the code more modular and
maintainable.
Understanding Function Borrowing with Bind
Suppose we have three objects representing users, each with a name and age property. We want each object to
have access to a sayHi method to display their name. Instead of defining the sayHi method for each object,
we can define it once and let the objects borrow this method using bind.

Initial Setup

First, let's define our user objects and the sayHi function:

const user1 = {
name: 'Prakash',
age: 25,
};

const user2 = {
name: 'Ashish',
age: 30,
};

const user3 = {
name: 'Ria',
age: 22,
};

function sayHi() {
[Link](`Hi, my name is ${[Link]}.`);
}

Using Bind

The bind method creates a new function that, when called, has its this keyword set to the provided value.
Unlike call and apply, bind does not immediately invoke the function. Instead, it returns a new function that
can be invoked later.

Here's how you can use bind to borrow the sayHi function for each user:
const boundSayHiUser1 = [Link](user1);
const boundSayHiUser2 = [Link](user2);
const boundSayHiUser3 = [Link](user3);

boundSayHiUser1(); // Output: Hi, my name is Prakash.


boundSayHiUser2(); // Output: Hi, my name is Ashish.
boundSayHiUser3(); // Output: Hi, my name is Ria.

Passing Arguments with Bind


The bind method can also be used to partially apply arguments to the function. This is useful if your function
takes additional parameters.

Let's modify our sayHi function to take additional parameters and use bind to pass these arguments:

function introduce(degree, year) {


[Link](`${[Link]}, Degree: ${degree}, Year: ${year}`);
}

const boundIntroduceUser1 = [Link](user1, '[Link] ECE', 2015);


const boundIntroduceUser2 = [Link](user2, '[Link] CS', 2018);
const boundIntroduceUser3 = [Link](user3, '[Link] CS', 2022);

boundIntroduceUser1(); // Output: Prakash, Degree: [Link] ECE, Year: 2015


boundIntroduceUser2(); // Output: Ashish, Degree: [Link] CS, Year: 2018
boundIntroduceUser3(); // Output: Ria, Degree: [Link] CS, Year: 2022

Flexibility with Bind

The flexibility of bind allows us to create reusable and modular code. It can also be used in event handlers and
other scenarios where the function needs to be invoked later.

Here's an example of using bind in an event handler:

In this example, the boundSayHiUser1 function will be invoked when the button is clicked, and it will have
its this keyword set to user1.

Summary

 Bind: Creates a new function that can be invoked later, with the this value permanently set to the specified object.
 Function Borrowing: Allows one object to use a method defined in another object.
 Partial Application: Bind can be used to partially apply arguments to a function, creating a new function with pre-set
arguments.
By using bind, we can keep our code clean, modular, and maintainable while avoiding code repetition.

Keep practicing this and solving questions around this concept to get a good hold of it. I'll see you in the next
lesson. Bye-bye!

const button = [Link]('button');


[Link] = 'Click me';
[Link](button);

[Link]('click', boundSayHiUser1);

Modules Introduction
Introduction to Modules in JavaScript
In modern JavaScript development, modules are vital in structuring, maintaining, and scaling applications. As
projects become complex, keeping all the logic in a single file becomes inefficient, error-prone, and hard to
maintain. This is where modules come into play, offering an organized and reusable approach to coding.

What are Modules in JavaScript?


A module in JavaScript is essentially a file that contains code, which can be reused across different parts of an
application or project. It allows developers to break a large codebase into smaller, manageable pieces. These
pieces can then be imported and used as needed in other files.

Why Do We Need Modules?


Organized Code

Modules allow you to split a large program into smaller, logically related files. For example:

 Logic related to students can reside in a [Link] file.


 Logic related to courses can be in a [Link] file. This makes it easier to locate, read, and modify the
code.

Reusability

If a function or logic is required in multiple places, modules allow you to define it once and reuse it elsewhere.
For instance: A utility function in [Link] can be reused across the entire application without rewriting it.

Better Maintainability

When code is split into modules, making updates or fixing bugs becomes faster and more straightforward. If you
know where specific logic resides (thanks to modular organization), you can quickly make changes without
hunting through a single, large file.

Collaboration Made Easy

In team environments, having all code in a single file can lead to merge conflicts and coordination issues.
Modules enable multiple developers to work on different files without interfering with each other. This
significantly improves collaboration.

Key Benefits Brought by Modules


 Reusability: Avoids code duplication by reusing logic across files.
 Maintainability: Organized files make it easier to understand and update code.
 Collaboration: Enables multiple developers to work simultaneously without conflicts.
 Clean Codebase: Keeps the project structure clean and manageable.

Conclusion
Modules in JavaScript are not just a convenience but a necessity for modern development. By using modules,
you can ensure your codebase remains efficient, even as your application grows in complexity. In the next
step, learning how to implement and use modules will take your development skills to the next level. Stay
tuned for further explanations and examples!

Understanding JavaScript modules

Understanding JavaScript Modules


In this article, we will explore the concept of modules in JavaScript, how they help in structuring applications,
and how you can use them effectively. JavaScript modules allow you to split your code into smaller,
manageable parts, which can be reused across different files. This approach makes code more organized,
maintainable, and scalable.

Creating a Simple Module in JavaScript


Let’s look at a practical example to understand better how modules work. We will create a simple JavaScript
project consisting of two modules:

 [Link]: The main file where we import functions from another module.
 [Link]: A utility module that contains a couple of functions.

Step-by-Step Implementation
Creating the [Link] File

First, create a new file named [Link] where we will define two functions: greet and print.

// [Link] greet(userName){ return `Good morning, ${userName}`;}function print(value) { [Link](value); }//


Exporting functions from the utils [Link] = { greet, print};

In [Link], the functions greet and print are defined. We then use [Link] to export these functions. This
makes them available to be imported in other files.
Creating the [Link] File

Now, let’s create [Link], which will import the functions from [Link] and use them.

// [Link]// Importing the utils moduleconst allTheModules = require("./[Link]");[Link]("any");

In this file, we use require('./utils') to import the functions from the [Link] module. Once imported, we can call
these functions as needed.

Running the Code

To run the code, follow these steps:

 Open your terminal.


 Navigate to the directory where [Link] and [Link] are located.
 Run the following command:
node [Link]

This will output:


any

Using Destructuring with Modules


If you want to simplify the code and directly access the functions from the module, you can use destructuring:

// [Link]// Destructuring the functions from the utils moduleconst {print, greet} = require("./[Link]");print(greet("Anything!"));

Here, we use destructuring to import greet and print directly from the utils module. This eliminates the need to
reference [Link] and [Link] each time.

Output:
Good morning Anything!

Conclusion
JavaScript modules are essential for writing clean, maintainable, and scalable code. By breaking your application
into smaller, reusable modules, you can keep things organized and make it easier to manage as your
codebase grows.

Using Import, Export, and Dynamic Imports in JavaScript

Using Import, Export, and Dynamic Imports in JavaScript


Dynamic imports in JavaScript and ReactJS allow developers to load modules only when needed, improving
performance and reducing unnecessary code execution. Let’s break down the concepts, steps, and benefits
of using dynamic imports while exploring key differences between static imports, default exports, named
exports, and dynamic imports.

Setting Up the Basics


Initializing a Project:

 Run npm init -y to initialize a [Link] project with default settings.


 This creates a [Link] file where you can define project configurations.

Defining the Module Type:

Add "type": "module" in [Link]. This specifies that the project will use ECMAScript Modules (ESM) instead
of CommonJS.

Configuration:
{
"name": "dynamic-import-demo",
"type": "module"
}

Scripts:

Define custom scripts for execution, such as:


"scripts":
{
"start": "node [Link]"
}

Import and Export


Default Export:

export default function greet() {

[Link]('Hello, World!');

This allows importing the default export with any name:


import greetFunction from './[Link]';

greetFunction();

Named Export:

export function greet() {

[Link]('Hello, World!');

Named exports require specifying the exact name while importing:

import { greet } from './[Link]';

greet();

Dynamic Imports

Why Use Dynamic Imports?

Dynamic imports allow you to load specific modules only when required. This reduces the initial load time and is
beneficial in large applications where only certain features or pages require specific modules.

Implementing Dynamic Imports

Example Use Case:

Suppose you have a [Link] file with the following function:

export function add(value1, value2) {

return value1 + value2;


}

Dynamic Import Syntax:

async function loadMath() {

const math = await import('./[Link]');

[Link]([Link](2, 3)); // Outputs: 5

loadMath();

Here, [Link] is loaded only when loadMath is executed.

await import() ensures the code waits for the module to load before using it.

Conditional Imports:

Dynamic imports can be used conditionally:

const isMathRequired = true;

if (isMathRequired) {

const math = await import('./[Link]');

[Link]([Link](4, 5));

Difference Between Static and Dynamic Imports


Feature

Static Imports

Dynamic Imports

Loading Time

Loaded during startup

Loaded on-demand

Use Case

For essential modules

For optional or large modules

Syntax

import module from '...'

await import('...')

Benefits of Dynamic Imports

Improved Performance:
Load only what is needed, reducing the overall bundle size.

Especially useful in ReactJS for code-splitting.

Resource Efficiency:

Avoid unnecessary module loading for users who don’t require certain features.

Modular Codebase:

Simplifies code by separating functionalities into smaller, self-contained modules.

ReactJS Example

In a ReactJS application, dynamic imports are used for lazy loading components:

import React, { Suspense } from 'react';

const LazyComponent = [Link](() => import('./LazyComponent'));

function App() {

return (

<Suspense fallback={<div>Loading...</div>}>

<LazyComponent />

</Suspense>

);

}
export default App;

[Link]() ensures the component is loaded only when required.

Suspense displays a fallback UI while the component loads.

Diagram: Dynamic vs Static Imports

Below is a diagram illustrating the difference between static and dynamic imports:

Static Import:

[Startup Time] --> [Load All Modules] --> [Execution]

Dynamic Import:

[Startup Time] --> [Load Essential Modules] --> [Conditionally Load Additional Modules]

Conclusion
Dynamic imports are a powerful feature in JavaScript and ReactJS, allowing developers to optimize application
performance by loading modules only when needed. By understanding the differences between static and
dynamic imports, and leveraging default and named exports effectively, you can build efficient and scalable
applications.

Execution Context in Javascript

Introduction
Execution context is a fundamental concept in JavaScript that dictates how the code is executed. Unlike many
other programming languages, JavaScript handles code execution in a unique way, making it essential to
understand this concept thoroughly.

Browser and JavaScript Engine


When a browser encounters JavaScript code, it activates the JavaScript engine. Each browser has its own
JavaScript engine (e.g., V8 in Chrome, SpiderMonkey in Firefox).

Execution Context in Javascript

Browser -> JavaScript Engine

Execution Context
The JavaScript engine creates an environment called the execution context to execute the code. This
environment manages the memory allocation and the execution of the code.

Types of Execution Context

1. Global Execution Context (GEC): Created when the JavaScript engine starts executing the code.
There is only one GEC per JavaScript file.
2. Functional Execution Context (FEC): Created whenever a function is invoked. There can be multiple
FECs depending on the number of function calls.

Components of Execution Context

1. Variable Object: Contains variable and function declarations.


2. Scope Chain: Manages the scope and scope chain.
3. this Keyword: Sets the value of this.

Creation of Execution Context


Execution context is created in two phases:

1. Creation Phase:
1. Memory allocation for variables and functions.
2. Variables declared with var are assigned undefined.
3. Function declarations are assigned the function definition.
2. Execution Phase:
1. Code is executed line by line.
2. JavaScript is a single-threaded synchronous language, meaning it executes one line of code at
a time in order.
Representation Of Global
Execution Context

Representation of
Functional Execution Context

Example

Consider the following code:

[Link]("Global Context Start");

function foo() {
[Link]("Inside foo");
}

function bar() {
[Link]("Inside bar");
foo();
}

bar();
[Link]("Global Context End");

Global Execution Context (GEC)


1. Creation Phase:
1. console is identified.
2. foo and bar are function declarations.
2. Execution Phase:
1. [Link]("Global Context Start") is executed.
2. bar() is called, creating a new FEC.

Functional Execution Context (FEC)

When bar() is called:

1. Creation Phase:
1. console is identified.
2. foo is identified within bar.
2. Execution Phase:
1. [Link]("Inside bar") is executed.
2. foo() is called, creating a new FEC.
When foo() is called:

1. Creation Phase:
1. console is identified.
2. Execution Phase:
1. [Link]("Inside foo") is executed.

Call Stack

The call stack maintains the order of execution contexts:

1. Start:
1. Call Stack: [Global Execution Context]
2. Executing bar():
1. Call Stack: [Global Execution Context, bar Execution Context]
3. Executing foo() inside bar:
1. Call Stack: [Global Execution Context, bar Execution Context, foo Execution Context]
4. Completion of foo():
1. Call Stack: [Global Execution Context, bar Execution Context]
5. Completion of bar():
1. Call Stack: [Global Execution Context]
6. Completion of Global Execution:
1. Call Stack: []

Importance of Understanding Execution Context


Understanding execution context is crucial for several reasons:

 Code Execution: It helps in understanding how JavaScript executes code line by line.
 Debugging: It aids in debugging by showing the sequence of function calls.
 Memory Management: It helps in understanding how memory is allocated and deallocated.
Conclusion
Execution context is a vital concept in JavaScript that dictates how code is executed. By understanding the
creation and execution phases of the execution context and how the call stack works, you can write more
efficient and bug-free code. This foundational knowledge will also help you grasp more advanced concepts
like closures, asynchronous programming, and event loops.

How JS executes code

In the previous lesson, we discussed the concept of execution context in JavaScript. Now, let's dive deeper into
how JavaScript code is executed concerning the execution context.

JavaScript Execution Context: An Overview


Whenever JavaScript encounters a code snippet, it activates the JavaScript engine, which creates an
environment called the execution context. This context is created in two phases:

1. Creation Phase: Allocates memory to variables and functions.


2. Execution Phase: Executes the code line by line.

Execution Phases Explained


Creation Phase

In the creation phase, the JavaScript engine:

 Scans through the code.


 Allocates memory for variables declared with var and function declarations.
 Assigns undefined to variables and stores the function definitions.

Execution Phase

In the execution phase, the JavaScript engine:

 Executes the code line by line.


 Updates the values of variables and executes functions.
PICTORIAL REPRESENTATION OF EXECUTION CONTEXT
Sample Code Execution
Consider the following sample code:

Now we write a demo code below and we will say line by line, how the code run.

var n = 3;
function squr(num) {
var ans = num * num;
return ans;
}
var three = squr(n);

When you run this whole code a global EXECUTION CONTEXT is created and it contains two parts one is
memory and the other is code execution.

When the first line is encountered it will reserve memory for all variables(n, three, five) and function(square).
When reserving the memory for variables it reserves a special value undefined and for function, it stores
whole code. the pictorial representation is shown below.

PICTORIAL REPRESENTATION OF GLOBAL EXECUTION CONTEXT


After allocating memory for all variables and function, code execution phase starts(code runs line by line).

Line 1: var n=3, 3 value placed into the n identifier.

Line 2-5: nothing to execute.

Line:6: we invoke a function, now function is the heart of JavaScript. The function is a mini-program and
whenever a new function is invoked all together a new EXECUTION CONTEXT is created(inside the code
execution phase). It also contains two-part memory and code execution phase. Memory is allocated for
variable and function(it involves function parameters and other variables).

PICTORIAL REPRESENTATION OF FUNCTION EXECUTION CONTEXT

After allocating memory, the code execution phase comes here the code inside the function executes, and
undefined is replaced by the actual value.

PICTORIAL REPRESENTATION OF EXECUTION CONTEXT WHILE FUNCTION EXECUTE


After that, when 'return' is encountered, the control of the program is returned to the place where the function
is invoked. The control goes to line 6, finding the answer in the local memory. The control then returns to
line 3, and the value of 'three' (undefined) is replaced by the value of 'ans'. After that, the entire execution
context is deleted.

PICTORIAL REPRESENTATION OF GLOBAL EXECUTION CONTEXT AFTER CODE EXECUTED

After that Global Execution Context is Deleted and our program ends. And One more thing, JavaScript Handle
everything deleted and created (to manage the execution context) it’s managing a stack. It's name CALL
STACK. It’s a Stack that maintains the order of execution.

Conclusion
The execution context is crucial for understanding how JavaScript code is executed. It consists of the creation
phase, where memory is allocated, and the execution phase, where the code is executed line by line. The
call stack helps manage the execution order of multiple functions, ensuring that JavaScript remains a single-
threaded synchronous language. Understanding these concepts is fundamental for writing efficient and bug-
free JavaScript code.

CallStack
In order to manage Different Execution Contexts, we have something called as CallStack present in the javascript
runtime. The job of the call stack is to manage and run execution contexts created while executing the code.
Let's try to understand this with the help of an example.

var x = 5 ; // Line 1
function getSum(num){
var y=7 ;
var total = num + y ;
return total ;

var result1 = getSum(x); // Line 9


var result2 = getSum(9); // Line 10

Once the code execution starts, the Global execution context is created and it will sit on the top Callstack . Once
the code execution reaches Line 9 new Function execution context is created for the getSum and now it will
sit on the top of Callstack . Similarly, this function will get executed line by line, and once finished it will be
popped out of the Callstack then execution for GEC will resume and once it gets finished it will also be
popped out of the stack.
In order to see how does this call stack looks like Go to Devtools => Sources => CallStack
Put a debugger at line 1 and you will see anonymous inside CallStack Tab.

Hoisting

In this lesson, we will explore what hoisting is and how it works in JavaScript. Hoisting is a crucial concept to
understand, especially when it comes to variables and functions.

Definition of Hoisting
Hoisting is a process whereby you can access the value of a variable or a function even before it is initialized. This
means that in JavaScript, declarations are moved to the top of their scope before code execution.

Example of Variable and Function Hoisting


Let's consider the following code:

var age = 100;


[Link](age); // Outputs: 100

function showName() {
[Link]("My name is Prakash Sakari");
}

showName(); // Outputs: My name is Prakash Sakari


Here, age is declared and initialized to 100, and showName is a function that logs a message to the console.

Hoisting with Function Declarations

Even if we invoke the function before its declaration, it still works due to hoisting:

showName(); // Outputs: My name is Prakash Sakari

function showName() {
[Link]("My name is Prakash Sakari");
}

Hoisting with Variable Declarations

Now, let's see what happens with variable declarations:

[Link](age); // Outputs: undefined


var age = 100;
[Link](age); // Outputs: 100
When we try to log age before its declaration, we get undefined. This is because the variable declaration is
hoisted, but its initialization is not. This is different from languages that throw an error when accessing a
variable before its declaration.

Function Expression Hoisting

Function expressions behave differently compared to function declarations:

[Link](getUserName); // Outputs: undefined


var getUserName = function() {
[Link]("My name is Prakash Sakari");
};
[Link](getUserName); // Outputs: function() { [Link]("My name is Prakash Sakari"); }
In this example, getUserName is treated as a variable. During the hoisting process, it is initialized
to undefined first, and later assigned the function.

Explanation of Hoisting with Execution Context


To understand hoisting, we need to delve into the execution context. The execution context consists of two
phases: the creation phase and the execution phase.

1. Creation Phase:
1. Variables declared with var are assigned undefined.
2. Functions are assigned their definition.
2. Execution Phase:
1. Code is executed line by line.

Visualizing Hoisting with Debugger

To visualize hoisting, let's use a debugger:

1. Place a breakpoint at the start of the code.


2. Observe the values of variables and functions.
Consider the following code:

var age = 100;


function showName() {
[Link]("My name is Prakash Sakari");
}
[Link](age);
showName();
When we run this code with a debugger, we can see the following:

 Before execution, age is undefined, and showName is a function.


 After execution, age is 100, and showName logs the message.

Hoisting with let and const

Hoisting with let and const is different. They are hoisted but not initialized, resulting in a ReferenceError if
accessed before initialization:

[Link](x); // Throws ReferenceError: Cannot access 'x' before initialization


let x = 9;

[Link](y); // Throws ReferenceError: Cannot access 'y' before initialization


const y = 10;
Key Takeaways
 Hoisting: Variables declared with var and function declarations are hoisted to the top of their scope.
 Function Expressions: Treated as variables, and thus, initialized to undefined during hoisting.
 Temporal Dead Zone: let and const variables are hoisted but not initialized, resulting in
a ReferenceError if accessed before initialization.

Conclusion
Hoisting is an essential concept in JavaScript that allows for accessing variables and functions before their actual
declaration in the code. Understanding this behavior can help avoid common pitfalls and write more
predictable JavaScript code. In the next lesson, we will explore scopes and scope chains, further expanding
our understanding of variable and function behavior in JavaScript.

Hoisting in let and const variable

Are let and const Variables Hoisted?

A common question during interviews or discussions is whether let and const variables are hoisted. The answer is
yes, they are hoisted. However, they exist in something called the "Temporal Dead Zone" (TDZ) until they
are initialized.

Understanding the Temporal Dead Zone (TDZ)


The TDZ is the time between the variable's hoisting and its initialization. During this period, accessing the
variable results in a ReferenceError. Let's explore this with some code examples.

let x=10 ;
var y=11 ;
[Link](x);
[Link](y);

Output

10
11
Output is 10 and 11 as expected.

Now let us Tweak it a little bit and see what happens when we try to access x and y before initializing them

Example-2:

[Link](y);
[Link](x);
let x = 10;
var y = 11;

If You try to Run the above code it will show an error saying "ReferenceError: Cannot access 'x' before
initialization".

Now Let us see what happens when we try to access a variable that is not even declared in a JS Programme

Example-3:

[Link](a);

Upon running the above code You will see an error saying "ReferenceError: a is not defined"

Now here comes the answer to the initial question of whether hoisting occurs in let and const or not. If You
look closely at example 2 the error says cannot access x before initialization but in example three the error is
"a is not defined". Since we can clearly see the error in the example is about not accessing variable x before
initialization it means that it must have existed somewhere in the memory before initialization but we are
unable to access it. this special place in memory that we cannot access is known as the Temporal Dead zone.
So let and const are hoisted but they exist in Temporal Dead Zone.
Exploring TDZ with a Debugger

To better understand the TDZ, we can use a debugger. Here's the setup:

//TDZ starts here


[Link](y);
[Link](x);
let x = 9 ; //TDZ ends here
[Link](x);

Debugger Example

1. Set a Breakpoint: Place a breakpoint before the variable initialization.


2. Inspect Variables: Observe the state of variables in the debugger.
When the code execution pauses at the breakpoint, you will see that x is in the TDZ, and accessing it results in
a ReferenceError.

Temporal Dead Zone

 The TDZ starts from the beginning of the block scope.


 The TDZ ends when the variable is initialized.

{
// TDZ starts
[Link](x); // Throws ReferenceError
let x = 9; // TDZ ends
[Link](x); // Outputs: 9
}

Understanding Hoisting with const


The behavior of const is similar to let regarding hoisting:

[Link](y); // Throws ReferenceError: Cannot access 'y' before initialization


const y = 10;
Again, this error indicates that the variable y is known to exist but is not accessible before its initialization.

Key Takeaways
 Hoisting: let and const variables are hoisted but exist in the TDZ until initialization.
 TDZ: The period from the start of the block until the variable is initialized.
 Errors: Accessing a variable in the TDZ results in a ReferenceError.

Summary

In summary, both let and const are hoisted but reside in the Temporal Dead Zone until initialized. Understanding
this behavior is crucial for avoiding errors and writing efficient JavaScript code. In future lessons, we'll delve
deeper into scopes, scope chains, and block scopes, which will further clarify these concepts.

Exercises

To solidify your understanding, try the following exercises:

1. Create a function and declare variables with var, let, and const inside it. Observe the behavior when
accessing them before and after initialization.
2. Use a debugger to visualize the TDZ for let and const variables.
Pure Functions

Pure functions are a fundamental concept in programming, especially when working with functional
programming paradigms and frameworks like React. They are important because they ensure predictability
and reliability in your code. Let's break down what makes a function "pure" and why it's crucial to
understand this concept.

What is a Pure Function?


A pure function has the following characteristics:

1. Takes Input (Arguments): It should accept parameters and use those inputs to produce a result.
2. Returns a Value: It always returns a value.
3. No Side Effects: The output of the function should not depend on any external state or variables
outside of its scope. This means the function should not modify any external state (like global
variables or passed-in objects/arrays).
4. Deterministic: Given the same input, a pure function will always return the same output. This
predictability is a key aspect of pure functions.

Example of a Pure Function

Here’s a simple example:

function doubleValue(number) {
return number * 2;
}

const result = doubleValue(5);


[Link](result); // 10
This function is pure because:

 It takes an input (number).


 It returns a value (number * 2).
 It doesn't modify any external variables.
 The result is always the same for the same input.

Impure Function Example

Let's see an example of an impure function:

const multiplier = 4;
function doubleValue(number) {
return number * multiplier;
}

const result = doubleValue(5);


[Link](result); // 20
This function is impure because:

 It relies on an external variable (multiplier).


 If multiplier changes, the output changes even if the input (number) stays the same.
 It’s no longer predictable since it depends on external state.

Avoiding Mutation

Another characteristic of pure functions is that they do not mutate their input values. Let's consider an example
that mutates an array:

function appendNumbers(arr) {
[Link](5, 6);
return arr;
}

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


const result = appendNumbers(numbers);
[Link](result); // [1, 2, 3, 4, 5, 6]
This function is impure because it mutates the original array. The arr that is passed into the function is directly
modified.

Making it Pure

To make this function pure, you should avoid mutating the original array:

function appendNumbers(arr) {
const newArr = [...arr, 5, 6];
return newArr;
}

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


const result = appendNumbers(numbers);
[Link](result); // [1, 2, 3, 4, 5, 6]
[Link](numbers); // [1, 2, 3, 4] (original array remains unchanged)
Here’s why this is a pure function:

 It creates a new array (newArr) instead of modifying the original one.


 It returns this new array, leaving the original array intact.
Why Pure Functions Matter

Pure functions are essential for several reasons:

 Predictability: Since pure functions always produce the same output for the same input, they are
easy to reason about and debug.
 Testability: Pure functions are easier to test because they don't rely on external state.
 Concurrency: Pure functions don’t have side effects, so they are safe to run in parallel or in a
concurrent environment.
 React and Functional Programming: Many modern frameworks and libraries, such as React, rely
heavily on the principles of pure functions to manage state and UI rendering efficiently.

Summary
A pure function in JavaScript:

 Accepts inputs and returns a value.


 Does not rely on or modify external state.
 Always produces the same output for the same input.
Understanding and writing pure functions is crucial for writing clean, maintainable, and bug-free code. As you
continue to work with JavaScript and frameworks like React, you'll see how important pure functions are in
practice.

First-Class Function

In JavaScript, functions are treated as "first-class citizens." But what does this mean? It means that functions in
JavaScript have the same status as other data types like strings, numbers, or objects. Functions can be:

1. Assigned to variables
2. Passed as arguments to other functions
3. Returned from other functions
These capabilities make JavaScript a powerful language, especially for functional programming.

1. Assigning a Function to a Variable


You can assign a function to a variable, making the function accessible via the variable name.

const greetMessage = function() {


[Link]("Hello, Prakash. Welcome to GeeksForGeeks!");
};

greetMessage(); // Output: Hello, Prakash. Welcome to GeeksForGeeks!


Output

Hello, Prakash. Welcome to GeeksForGeeks!

Here, greetMessage is a variable that holds a function. When you call greetMessage(), it executes the function.

2. Passing a Function as an Argument to Another Function


You can pass a function as an argument to another function, which can then execute it or use it in some way.

function wrapperFunction() {
return "Welcome to GeeksForGeeks!";
}

function greetMessage(wrapper, name) {


const message = wrapper();
[Link](`${name}, ${message}`);
}

greetMessage(wrapperFunction, "Prakash"); // Output: Prakash, Welcome to GeeksForGeeks!

Output

Prakash, Welcome to GeeksForGeeks!

In this example, wrapperFunction is passed as an argument to greetMessage. Notice that we pass the reference of
the function (wrapperFunction) without parentheses, meaning the function is not executed immediately.
Inside greetMessage, we call wrapper() to execute the function.

3. Returning a Function from Another Function


Functions can also return other functions. This feature is often used in functional programming.

function greetMessage() {
return function() {
[Link]("Prakash, Welcome to GeeksForGeeks!");
};
}

const output = greetMessage();


output(); // Output: Prakash, Welcome to GeeksForGeeks!
Output

Prakash, Welcome to GeeksForGeeks!

In this example, greetMessage returns another function. When we call greetMessage(), it returns the inner
function, which we then store in the output variable. Finally, we call output() to execute the returned
function.

Alternatively, you can also call the returned function directly:


greetMessage()(); // Output: Prakash, Welcome to GeeksForGeeks!

Here, greetMessage() is called first, which returns the inner function, and then the returned function is
immediately executed with the second pair of parentheses.

Why Are First-Class Functions Important?


First-class functions are the foundation of many powerful programming patterns in JavaScript, such as:

 Callbacks: Functions passed as arguments to be executed later.


 Closures: Functions that capture and remember their lexical environment.
 Higher-Order Functions: Functions that return other functions or take functions as arguments.
Understanding first-class functions will make it easier to grasp these advanced concepts and write more flexible
and reusable code.

Higher-Order Function

Higher-order functions (HOFs) are a key concept in functional programming, allowing for more abstract and
flexible code. A higher-order function is a function that does at least one of the following:

1. Takes one or more functions as arguments.


2. Returns a function as a result.
HOFs enable you to write more reusable and concise code, especially when dealing with repetitive or complex
operations.

1. Basic Example of Higher-Order Functions


Let's start with a basic example where a function accepts another function as an argument:

function wrapper() {
return "Welcome to GFG";
}
function greetMessage(wrapper, name) {
[Link](`${name}, ${wrapper()}`);
}

greetMessage(wrapper, "Prakash"); // Output: Prakash, Welcome to GFG


In this example, greetMessage is a higher-order function because it accepts wrapper, another function, as an
argument. The wrapper function is called within greetMessage, allowing us to dynamically insert different
messages.

2. Returning Functions from a Function


Higher-order functions can also return another function. Let's look at an example:

function displayMessage() {
return function() {
[Link]("Hello from the inner function");
};
}

const output = displayMessage();


output(); // Output: Hello from the inner function
Here, displayMessage is a higher-order function because it returns another function. When displayMessage is
called, it returns the inner function, which is then assigned to output. We can then call output() to execute
the returned function.

3. Combining Both Concepts


Now, let's combine both concepts by writing a function that both accepts and returns functions:

function calculatePower(power) {
return function(number) {
return [Link](number, power);
};
}

const square = calculatePower(2);


const cube = calculatePower(3);

[Link](square(4)); // Output: 16
[Link](cube(3)); // Output: 27
In this example, calculatePower is a higher-order function that returns a new function tailored to the specific
power you want to apply. square and cube are both functions generated by calculatePower, each configured
to raise numbers to the second and third power, respectively.

4. Applying Higher-Order Functions to Arrays


Higher-order functions are particularly useful when working with arrays in JavaScript, especially with methods
like map, filter, and reduce.

Example: Using HOF with Array

Let's say you have an array of numbers, and you want to create a higher-order function to calculate different
powers of the numbers in the array.

function calculatePower(wrapper, arr) {


const tempArr = [];
for (let number of arr) {
[Link](wrapper(number));
}
return tempArr;
}

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

function cube(number) {
return number ** 3;
}

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

const squaredNumbers = calculatePower(square, arr);


[Link](squaredNumbers); // Output: [1, 4, 9, 16, 25]

const cubedNumbers = calculatePower(cube, arr);


[Link](cubedNumbers); // Output: [1, 8, 27, 64, 125]
Here, calculatePower is a higher-order function that takes a function ( wrapper) and an array as arguments.
The wrapper function (which can be square, cube, or any other function) is applied to each element in the
array.

Summary
Higher-order functions are a powerful feature in JavaScript that allows for more abstract, reusable, and flexible
code. They are foundational in functional programming and are commonly used in array methods
like map, filter, and reduce.

map(), reduce() and filter() functions


The map(), reduce() and filter() are array functions that transform the array according to the applied function
and return the updated array. They are used to write simple, short and clean codes for modifying an array
instead of using the loops.

 map() method: It applies a given function on all the elements of the array and returns the updated
array. It is the simpler and shorter code instead of a loop. The map is similar to the following code:

arr = new Array(1, 2, 3, 6, 5, 4);


for(let i = 0; i < 6; i++) {
arr[i] *= 3;
}
[Link](arr);

Output

[ 3, 6, 9, 18, 15, 12 ]

 Syntax:
[Link](function_to_be_applied)
[Link](function (args) {
// code;
})

 Example:

function triple(n){
return n*3;
}
arr = new Array(1, 2, 3, 6, 5, 4);

var new_arr = [Link](triple)


[Link](new_arr);

Output

[ 3, 6, 9, 18, 15, 12 ]

 reduce() method: It reduces all the elements of the array to a single value by repeatedly applying a
function. It is an alternative of using a loop and updating the result for every scanned element.
Reduce can be used in place of the following code:
arr = new Array(1, 2, 3, 6, 5, 4);
result = 1
for(let i = 0; i < 6; i++) {
result = result * arr[i];
}
[Link](result);

Output

720

 Syntax:
[Link](function_to_be_applied)
[Link](function (args) {
// code;
})

 Example:

function product(a, b){


return a * b;
}
arr = new Array(1, 2, 3, 6, 5, 4);

var product_of_arr = [Link](product)


[Link](product_of_arr)

Output

720

 filter() method: It filters the elements of the array that return false for the applied condition and
returns the array which contains elements that satisfy the applied condition. It is a simpler and
shorter code instead of the below code using a loop:

arr = new Array(1, 2, 3, 6, 5, 4);


new_arr = []
for(let i = 0; i < 6; i++) {
if(arr[i] % 2 == 0) {
new_arr.push(arr[i]);
}
}
[Link](new_arr);

Output

[ 2, 6, 4 ]

 Syntax:
[Link](function_to_be_applied)
[Link](function (args) {
// condition;
})

 Example:

arr = new Array(1, 2, 3, 6, 5, 4);


var new_arr = [Link](function (x){
return x % 2==0;
});

[Link](new_arr)

Output

[ 2, 6, 4 ]

Argument Object

All the regular functions instead of Arrow functions have a special Object called Arguments Object that contains
all the arguments passed to a function. It is an array Like Object present locally inside a function and it
contains all the arguments passed to a function.

In javascript, if we pass more arguments than the specified parameters it won't give us an error. let's try to
understand this with an example -

function calculateTotal(a,b){
return a + b;
}

const total = calculateTotal(3,4,5,6,7,8,9);


[Link](total);

Output

As the output is 7 so it is true that it is not giving us an error but what is happening with the other
arguments passed in a function call.
here is the argument object that comes into play. It stores all the arguments provided to it . Remember it is
not a usual Object but an array-like Object. So we have a limit over the operations that we can perform over
this arguments Object.

function calculateTotal(a,b){
[Link](arguments);
}

calculateTotal(3,4,5,6,7,8,9);

Output

[Arguments] { '0': 3, '1': 4, '2': 5, '3': 6, '4': 7, '5': 8, '6': 9 }

so it looks like an array-like Object with key-value [Link] can perform indexing over this objects.
if we want to change the value of a particular index we can do so as well

function calculateTotal(a,b){
arguments[0]= 9;
[Link](arguments);
}

calculateTotal(3,4,5,6,7,8,9);

Output

[Arguments] { '0': 9, '1': 4, '2': 5, '3': 6, '4': 7, '5': 8, '6': 9 }


You can see the value at index 0 is changed to 9.

We also have some caveats in this argument Object.


we can use the length method over this but we cannot use methods like map, filter, reduce that we use on
normal Arrays.

So the solution to this problem is to convert the arguments object into an array so that we can use all the
methods that are generally available for arrays.

function calculateTotal(a,b){
const arr1 = [...arguments];
[Link](arr1);
[Link](arguments);
}

calculateTotal(3,4,5,6,7,8,9);

Output

[
3, 4, 5, 6,
7, 8, 9
]
[Arguments] { '0': 3, '1': 4, '2': 5, '3': 6, '4': 7, '5': 8, '6': 9 }

Lets see what happens to the argument object when we have a Default parameter in our function :

function hello(a = 10){


[Link](a); // line2
[Link](arguments); //line3
arguments[0] = 9; // line4
[Link](arguments); //line5
[Link](a); //line6
}

hello(4);

Output
4
[Arguments] { '0': 4 }
[Arguments] { '0': 9 }
4

In case of default Parameter

Here in line 2 when the value of a is 4 as this was the argument passed to the hello function when it was called
so the default value of a is changed to 4 from 10.
Now when argument object value at zero index was changed to 9 .Will it going to change the value of a as
well?
No. Changing the argument object won't change the value of 'a'. The value of 'a' will be the initial value that
was passed through the first call of the hello(4) method.

Rest parameter

The rest parameter is very similar to arguments Objects but it has some subtle differences. Let us try to
understand it with the help of an example.

function calculateTotal(a,b,...rest){
[Link](a);
[Link](b);
[Link](rest);
}

calculateTotal(2,3,4,5,7,8,9,11.16);

Output

2
3
[ 4, 5, 7, 8, 9, 11.16 ]
So basically rest parameter collects all the remaining arguments and forms an array containing all of them as the
name suggests rest parameter.

The most important Point to remember about the rest parameter is that it should always be used as the last
parameter of the function otherwise there will be a syntax error.

The rest parameter is valuable when you are unsure about the number of arguments a function will have. It
collects all these arguments into an array, allowing you to perform various manipulations to achieve the
desired results using that array.

Variable Scope - Global, Local and Block Scope

When writing JavaScript code, one of the most fundamental concepts to grasp is variable scope. Understanding
the scope of a variable is crucial because, in real-world applications, functions often nest within each other,
creating different levels of visibility and accessibility for variables. This article will walk you through the
different types of scope in JavaScript, helping you understand where and how variables can be accessed.

Consider You are sitting in a room. How far can you see?

You can see only inside the room because that is where your vision can go and is limited to see inside those walls
of the room.
Similarly, Scope in Programming is where can a variable be accessed in the environment where it is declared
that is the visibility where the variable can be used.

We generally have three types of scope


1) Global Scope
2) Local Scope
3) Block Scope

Example of Global Variable:

var x = 6 ; //Global Scope

function hello(){

[Link](x);

}
hello();

Output

Variable x is written in the top-level code so it is global scope and javaScript has this concept that even inside a
hello function x is not declared but it is still able to console the value of x from inside the function as the
variable x is global Scope and this is how it works in Javascript.

Example Of Local Variable

var x = 6 ; //Global Scope

function hello(){
var y = 17; // Local Scope
[Link](x);
[Link](y);
}

hello();

Output

6
17

Inside Function hello(), variable y is local Scope as it can only be accessed within the function, if you try to access
it outside the function it will show a syntax error that y is not declared.
Even if We use let and const variable declaration, Global and Local variable concepts will work the same
way.

Let us Now Understand About the type of Scope


Global Scope - visibility all over the javascript Code
Block Scope - visibility only inside a piece of code generally wrapped by curly braces

A block in programming is generally a way to wrap multiple lines of code to define that they work in series
and we use { } brackets to define a Block Scope Example - for loop functions and if Block.

let and const declared variables are Block Scope and variables declared with keyword var are either global scope
or function Scoped.
Consider this Example
{
let a = 10 ;
let b = 20 ;
}

[Link](a);
[Link](b);

If we try to compile this code it will throw us an error as a and b are let declarations so they are only block
Scope .lets see what happens when we try the same code with var declared variable.

{
var a = 10 ;
var b = 20 ;
}

[Link](a);
[Link](b);

Output

10
20

If we try to do the same with var declared variable it will give us the output as
10
20
because var is either Global scope or Local Scope.

What if we try to use a var declared variable inside a function ?

In that case, they will act as a local variable and can only be accessed from inside the function. Example

function hello() {
var a = 10 ;
var b = 20 ;
}

[Link](a);
[Link](b);
This code will give us an error if we try to compile it because no matter if var declaration is used since a and b are
declared inside the function they will act as a local variable containing the scope only within the function.

So to summarize variables declared with var have Global Scope and variables declared with let and const
have block Scope.
When a variable is declared with var keyword inside an if block it has a global scope but when it is declared
inside a function it becomes a local variable of that function and cannot be accessed outside that function.
Variable declared with let and const always have block Scope.

Differences Between var, let, and const in Terms of Scope

 var: Variables declared with var are either globally scoped or function scoped, meaning they do not
adhere to block scope. If declared inside a block, they are still accessible outside the block.
Example:

if (true) {
var a = 10;
}
[Link](a); // Output: 10
 let and const: Variables declared with let or const are block scoped, meaning they are only accessible
within the block where they are defined.
Example:

if (true) {
let b = 20;
}
[Link](b); // Error: b is not defined

Why Understanding Scope is Important

Understanding scope is critical for several reasons:

1. Avoiding Bugs: Knowing where a variable can be accessed helps prevent unintended modifications to
variables, reducing the likelihood of bugs.
2. Memory Efficiency: Variables in local and block scopes are garbage collected after their execution
context is completed, which optimizes memory usage.
3. Code Clarity: Proper use of scope makes your code easier to read and maintain, as the flow of data
and variable usage is more predictable.

Conclusion
Grasping the concept of scope in JavaScript is essential for writing clean, efficient, and bug-free code. By
understanding global, local, and block scopes, along with how var, let, and const differ in their scope
behavior, you can better control the visibility and lifecycle of your variables. Practice and experimentation
with these concepts will solidify your understanding and enhance your coding skills.

Scope and Scope Chain

In JavaScript, scope defines the accessibility or visibility of variables and functions. We’ve already explored
global, local, and block scopes, but now we dive into a more advanced concept: the scope chain. The scope
chain is an essential part of how JavaScript manages and resolves variables during execution.

Recap of Scopes
 Global Scope: Variables declared outside any function or block. Accessible anywhere in the code.
 Local Scope: Variables declared within a function. Accessible only within that function.
 Block Scope: Variables declared with let or const inside a block (e.g., loops, conditionals). Accessible only within that
block.

What is a Scope Chain?

A scope chain is the mechanism that JavaScript uses to find variables. When a variable is accessed, JavaScript
first looks in the current scope. If it doesn’t find the variable, it moves up to the outer scope, continuing until
it either finds the variable or reaches the global scope. If the variable is not found in the global scope, a
reference error is thrown.

Example of Scope Chain

Consider this code:

let a = 3;

function x() {
let b = 5;

function y() {
let c = 7;

function z() {
[Link](a); // Logs 3
[Link](b); // Logs 5
[Link](c); // Logs 7
}
z();
}

y();
}

x();

Output

3
5
7

How Scope Chain Works


Let us try to Understand the Scope Chain with respect to Execution Context and Lexical Environment.

1. Global Execution Context:


o When the script starts, the global execution context is created. This context includes the global scope.
o The global scope contains the variable a = 3 and the function x.
2. Function x Execution:
o When x is called, a new execution context for x is created.
o This context includes the local scope of x, which contains the variable b = 5 and the function y.
o The scope chain for x includes its local scope and the global scope.
3. Function y Execution:
o When y is called within x, a new execution context for y is created.
o This context includes the local scope of y, which contains the variable c = 7 and the function z.
o The scope chain for y includes its local scope, the local scope of x, and the global scope.
4. Function z Execution:
o When z is called within y, a new execution context for z is created.
o This context includes the local scope of z, which does not contain any variables but has access to a, b,
and c through the scope chain.
o The scope chain for z includes its local scope, the local scope of y, the local scope of x, and the global scope.

Lexical Environment and Scope Chain

The lexical environment is a theoretical concept that refers to the environment in which code is written and
executed. It includes:

1. Environment Record: This stores all variable and function declarations.


2. Reference to Outer Lexical Environment: This connects to the parent lexical environment, forming a chain back to the
global environment.
The scope chain is made possible by this lexical environment. Each function and block of code has its own lexical
environment, which links to its parent environment, creating the chain.

Visualization with Execution Contexts

To better understand the scope chain, let’s visualize the execution context and lexical environments:
 Global Execution Context: Contains a = 3 and function x.
 Function x Execution Context: Contains b = 5 and function y. References the global lexical environment.
 Function y Execution Context: Contains c = 7 and function z. References the lexical environment of x.
 Function z Execution Context: Has access to a, b, and c through its scope chain.

Why Scope Chains Are Important

Understanding scope chains is crucial because it helps in:

1. Debugging: Knowing how and where JavaScript looks for variables helps in diagnosing issues.
2. Memory Management: Avoiding unnecessary global variables reduces memory leaks.
3. Optimization: Writing code that leverages local scopes and minimizes reliance on the global scope improves
performance.

So Scope chain is Possible Due to something called a lexical Environment .


A lexical environment in JavaScript refers to the set of variables, functions, and other data structures that
are available in a particular section of code during its execution. It consists of two parts: a variable
environment and a reference to the outer lexical environment

Whenever a function executes it has 2 things.


1)Variable Environment
2)Reference to Outer Lexical Environment that is the Parent's lexical Environment.

So if we analyze the above code


when x() is invoked its variable environment will have a variable b and function y but it will also have an
access to its outer lexical Environment which is the global lexical environment in this case so since function x
does not have a variable a declared inside it, it is still able to access a which is present in its outer lexical
Environment. This is because every function has access to its outer lexical Environment as well.

The above explanation is valid for the function invocation of y() as well since function y() only has variable c
and function z() in its variable environment, it is still able to [Link](b) because it has an excess to its
outer lexical environment which is function x() in case of function y().

The above explanation is valid for the function invocation of function z() , since function z() has only access
to variable d in its variable environment it is still able to access variable c and print its value which is present
or declared in function y, the same explanation holds true that it also has a reference to its parent
environment as well which is function y().

Conclusion

The scope chain is a fundamental concept in JavaScript that determines how variables are resolved in different
execution contexts. By understanding how scope chains work and the role of lexical environments, you can
write more efficient and bug-free code. This concept also sets the stage for more advanced topics like
closures and higher-order functions, which build upon the idea of scope chains

Recursion

Recursion is one of the most powerful and elegant techniques in programming. At its core, recursion is when a
function calls itself in order to solve a problem. While it may seem complex at first, once understood, it can
be an invaluable tool in your programming toolkit.

What is Recursion?

Recursion is a programming concept where a function calls itself in order to break down a problem into smaller,
more manageable parts. The key idea is to solve a small piece of the problem and then use the solution of
that small piece to solve the next piece, and so on, until the entire problem is solved.

Sum of elements of an array using recursion

// JavaScript program to find sum of array


// elements using recursion.

// Return sum of elements in A[0..N-1]


// using recursion.
function findSum(A, N) {
if (N <= 0)
return 0;
return (findSum(A, N - 1) + A[N - 1]);
}

// Driver code

let A = [1, 2, 3, 4, 5];


let N = [Link];
const total = findSum(A,N);
[Link](total);

Output

15

Have a look at the image representation of every step of the function call .
Factorial of a number using recursion

// Javascript to find factorial


// of given number
// function to find factorial
// of given number
function factorial(n) {
if (n == 0) return 1;
return n * factorial(n - 1);
}

// Driver Code
let num = 5;
const fact = factorial(num);
[Link](fact);

Output

120
Factorial using a loop:

function factorial(number) {
let total = 1;
for (let i = number; i > 0; i--) {
total *= i;
}
return total;
}

[Link](factorial(5)); // Output: 120


Output

120

Key Points to Remember

 Base Case: A condition that stops the recursion. Without it, the recursion would run indefinitely.
 Recursive Case: The part of the function where the function calls itself with a smaller or simpler problem.
 Stack Overflow: Recursion relies on the function call stack. If the recursion depth is too large, it can lead to a stack
overflow error.

When to Use Recursion

Recursion is particularly useful for problems that can naturally be divided into similar subproblems, such as:
 Calculating factorials
 Summing numbers
 Traversing tree or graph structures
 Solving puzzles like the Tower of Hanoi
 Implementing algorithms like quicksort or mergesort

Conclusion

Recursion is a powerful technique that, when understood, can make certain problems easier to solve and your
code more elegant. However, it requires careful handling, particularly ensuring that you have a proper base
case to prevent infinite recursion. Practice with different problems, and you'll soon appreciate the beauty
and power of recursion in programming.

Closures

When you start learning programming, certain concepts can seem daunting, especially when they appear under
"advanced topics." One such concept in JavaScript is closures. Despite their reputation for being difficult,
closures are fundamental and, once understood, become a powerful tool in your coding arsenal. This guide
will demystify closures, explaining what they are, how they work, and why they are so important.

What is a Closure?

A closure is essentially a function bundled together with its surrounding state (the lexical environment). In
simpler terms, a closure is a function that remembers the variables from the place where it was defined,
even after that place is no longer accessible.

Definition:
1. Technical Definition: A closure is a combination of a function and its lexical environment within which that function was
declared.
2. Simplified Definition: A closure is a function that can access and "remember" variables from its outer function even after
the outer function has finished executing.

How Does a Closure Work?

To understand closures, it’s important to grasp the concepts of scope, scope chain, and lexical environment.
Let's dive into an example to see closures in action.

Example: Basic Closure

function outerFunction() {
let outerVariable = 10;

function innerFunction() {
[Link](outerVariable); // Accesses outerVariable
}

return innerFunction;
}

const myClosure = outerFunction(); // Returns the innerFunction


myClosure(); // Executes innerFunction, logs 10

Output

10

Explanation:

 outerFunction creates a variable outerVariable and defines innerFunction.


 innerFunction is returned and assigned to myClosure.
 Even after outerFunction has finished executing, myClosure (which is innerFunction) still has access
to outerVariable because of the closure.
This example illustrates the key feature of closures: retaining access to the scope of the outer function even
after the outer function has finished execution.

Closures in Action

Example: Maintaining State with Closures

function counter() {
let count = 0;
return function() {
count++;
return count;
};
}

const increment = counter();


[Link](increment()); // 1
[Link](increment()); // 2
[Link](increment()); // 3

Output

1
2
3

Here, the counter function creates a count variable and returns an inner function that increments and
returns count. Each time increment is called, it increases the value of count, showing that the inner function
remembers the state of count across multiple [Link]-1

Why Are Closures Important?

Closures are powerful because they allow for:


 Data Encapsulation: Variables within a closure are not accessible from the outside, creating a private scope.
 Persistent State: Functions can retain state between executions, which is useful in many scenarios like creating counters,
managing event listeners, or even building modules.
 Higher-Order Functions: Closures are fundamental to understanding concepts like callbacks, functional programming,
and higher-order functions.

Common Pitfalls and Considerations

While closures are powerful, they can also introduce complexity, especially when dealing with variables that
change over time. Consider the following example:

function createFunctions() { let functions = []; for (var i = 0; i < 3; i++) { [Link](function() { [Link](i);
}); } return functions;}
const funcs = createFunctions();funcs[0](); // 3funcs[1](); // 3funcs[2](); // 3

Output

3
3
3
What’s Happening?

All functions returned by createFunctions log the value 3. This happens because var is function-scoped, and by the
time the functions are invoked, the loop has completed, leaving i with the value 3.

Solution:
Using let instead of var:

function createFunctions() {
let functions = [];
for (let i = 0; i < 3; i++) {
[Link](function() {
[Link](i);
});
}
return functions;
}

const funcs = createFunctions();


funcs[0](); // 0
funcs[1](); // 1
funcs[2](); // 2

Output

0
1
2

Now, each function correctly remembers its own i value due to block-scoping provided by let.

Conclusion

Closures are a foundational concept in JavaScript that allow functions to maintain access to variables even after
the outer function has finished execution. By mastering closures, you gain the ability to write more robust,
modular, and efficient code.

Whether you're creating private variables, persistent states, or sophisticated functional programming patterns,
closures are an indispensable tool. With practice, the concept of closures will become second nature,
opening up new possibilities in your JavaScript development journey.

What is DOM?
The Document Object Model, or DOM, is a critical concept in web development. It serves as the interface
between HTML documents and JavaScript, enabling scripts to dynamically access and update the content,
structure, and style of a document.

What is the DOM?

The DOM stands for Document Object Model. It represents the HTML structure of a webpage in a tree-like
format, where each node corresponds to an element in the document. This structure allows programming
languages like JavaScript to interact with the document in a structured way, manipulating elements,
attributes, and content.

How and When is the DOM Created?

The creation of the DOM follows a specific process during the page load:

1. HTML Loading: The browser first loads the HTML document.


2. HTML Parsing: As the browser loads the HTML, it begins parsing it from top to bottom.
3. DOM Tree Creation: During parsing, the browser constructs the DOM tree. This tree represents the hierarchical structure
of the HTML document.

Structure of the DOM Tree

The DOM tree starts with the HTML element as the root, which branches out into child nodes such
as HEAD and BODY. These child nodes further branch out into their own child nodes, forming a tree structure.

Properties of DOM

HTML
├── HEAD
│ ├── META
│ ├── TITLE
│ └── LINK
└── BODY
├── H1
├── DIV
│ ├── P
│ ├── BUTTON
│ └── A
└── SECTION
├── ARTICLE
│ ├── P
│ └── SPAN
 Window Object: Window Object is object of the browser which is always at top of the hierarchy. It is like an API that is
used to set and access all the properties and methods of the browser. It is automatically created by the browser.
 Document object: When an HTML document is loaded into a window, it becomes a document object. The ‘document’
object has various properties that refer to other objects which allow access to and modification of the content of the web
page. If there is a need to access any element in an HTML page, we always start with accessing the ‘document’ object.
Document object is property of window object.
 Form Object: It is represented by form tags.
 Link Object: It is represented by link tags.
 Anchor Object: It is represented by a href tags.
 Form Control Elements: Form can have many control elements such as text fields, buttons, radio buttons, checkboxes,
etc.

Why is the DOM Tree Created?

The DOM tree is created to allow JavaScript to interact with the HTML document. Since JavaScript cannot
directly understand HTML, the DOM provides a structured model that JavaScript can manipulate. This allows
for tasks like searching for elements, adding event listeners, modifying content, and updating styles.

Manipulating the DOM

JavaScript interacts with the DOM using various methods:

 Searching for Elements: Methods like [Link](), [Link](),


and [Link]() allow you to select elements in the DOM.
 Modifying Elements: Once an element is selected, its content, attributes, and styles can be changed using properties and
methods like innerHTML, setAttribute(), and style.
 Event Handling: Event listeners can be added to DOM elements to respond to user interactions, such as clicks or key
presses.

The Role of DOM in Webpage Rendering

The DOM is crucial in rendering a webpage. The process is as follows:

1. HTML Loading and Parsing: The browser loads and parses the HTML to create the DOM.
2. CSS Loading and Parsing: Concurrently, the browser loads and parses the CSS, creating the CSS Object Model (CSSOM).
3. Render Tree Creation: The DOM and CSSOM are combined to create the render tree, which represents the document's
content and styles.
4. Layout and Painting: The render tree is used to calculate the layout, determining the position and size of each element.
Finally, the browser paints the elements onto the screen.

Conclusion

Understanding the DOM is fundamental to web development. It is the foundation upon which JavaScript
interacts with a webpage, allowing for dynamic content manipulation, user interaction, and responsive
design. By understanding how the DOM works, you can harness the full power of JavaScript to create
interactive and engaging web applications.

Searching the DOM

HTML DOM getElementByID() Method

The getElementById() method returns the elements that have given an ID which is passed to the function. This
function is a widely used HTML DOM method in web designing to change the value of any particular element
or get a particular element. If the passed ID to the function does not exist then it returns null. The element is
required to have a unique id, in order to get access to that specific element quickly, & also that
particular id should only be used once in the entire document.

Syntax:
[Link]( element_ID )

Parameter: This function accepts single parameter element_ID which is used to hold the ID of the element.

Return Value: It returns the object of the given ID. If no element exists with the given ID then it returns null.

Example 1: This example describes the getElementById() method where element_id is used to change the color
of the text on clicking the button.

<!DOCTYPE html>
<html>

<head>
<title>
DOM getElementById() Method
</title>

<script>

// Function to change the color of element


function geeks() {
var demo = [Link]("geeks");
[Link] = "green";
}
</script>
</head>

<body style="text-align:center">
<h1 id="geeks">GeeksforGeeks</h1>
<h2>DOM getElementById() Method</h2>
<!-- Click on the button to change color -->
<input type="button"
> value="Click here to change color" />
</body>

</html>

Example 2: This example describes the getElementById() method where the element_id is used to change the
content on clicking the button.

<!DOCTYPE html>
<html>

<head>
<title>
DOM getElementById() Method
</title>

<script>

// Function to change content of element


function geeks() {
var demo = [Link]("geeks");
[Link] = "Welcome to GeeksforGeeks!";
}
</script>
</head>

<body style="text-align:center">
<h1>GeeksforGeeks</h1>
<h2>DOM getElementById() Method</h2>
<h3 id="geeks">Hello Geeks!</h3>

<!-- Click here to change content -->


<input type="button"
> value="Click here to change content" />
</body>

</html>

DOM querySelectorAll() Method

The querySelectorAll() method in HTML is used to return a collection of an element’s child elements that match
a specified CSS selector(s), as a static NodeList object. The NodeList object represents a collection of nodes.
The nodes can be accessed by index numbers. The index starts at 0.
Note: If we want to apply CSS property to all the child nodes that match the specified selector, then we can
just iterate through all nodes and apply that particular property.
Syntax:

[Link](selectors)

Selectors is the required field. It specifies one or more CSS selectors to match the [Link] selectors are
used to select HTML elements based on their id, classes, types, etc.
In case of multiple selectors, comma is used to separate each selector.
Example:

<!DOCTYPE html>
<html>
<head>
<title>DOM querySelectorAll() Method</title>
<style>
#geek {
border: 1px solid black;
margin: 5px;
}
</style>
</head>
<body style = "text-align: center;">
<h1 style = "color: green;">GeeksforGeeks</h1>
<h2>querySelectorAll() Method</h2>
<div id="geek">

<p>This is paragraph 1.</p>

<p>This is paragraph 2.</p>

</div>
<button it</button>
<script>
function myFunction() {
var x = [Link]("geek").querySelectorAll("p");
var i;
for (i = 0; i < [Link]; i++) {
x[i].[Link] = "green";
x[i].[Link] = "white";
}
}
</script>
</body>
</html>
Event Listener

An event is an important part of JavaScript.A web page respond according to an event occurred. Some events
are user generated and some are generated by API’s. An event listener is a procedure in JavaScript that
waits for an event to occur. The simple example of an event is a user clicking the mouse or pressing a key on
the keyboard.

The addEventListener() is an inbuilt function in JavaScript which takes the event to listen for, and a second
argument to be called whenever the described event gets fired. Any number of event handlers can be added
to a single element without overwriting existing event handlers.

Syntax:
[Link](event, listener, useCapture);

Parameters:
 event : event can be any valid JavaScript [Link] are used without “on” prefix like use “click” instead of “onclick” or
“mousedown” instead of “onmousedown”.
 listener(handler function) : It can be a JavaScript function which respond to the event occur.
 useCapture: It is an optional parameter used to control event propagation. A boolean value is passed where “true”
denotes capturing phase and “false” denotes the bubbling phase.
JavaScript Code to show the working of addEventListener() method :

code #1:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Listener Example</title>
</head>
<body>

<button id="myButton">Click me</button>


<p id="geek"></p>

<script>
// Get the button element by its ID
var button = [Link]("myButton");
var geek=[Link]("geek")

// Define the event handler function


function handleClick() {
// alert("Button clicked!");
[Link]='<H1>GeeksforGeeks</H1>'
}

// Attach the event listener to the button


[Link]("click", handleClick);

</script>

</body>
</html>

Output:

Text appears when button is clicked

code #2:
In this example two events “mouseover” and “mouseout” are added to the same element. If the text is
hovered over then “mouseover” event occur and RespondMouseOver function invoked, similarly for
“mouseout” event RespondMouseOut function invoked.

<!DOCTYPE html>
<html>

<body>
<button id="clickIt">Click here</button>

<p id="hoverPara">Hover over this Text !</p>

<b id="effect"></b>
<script>
const x = [Link]("clickIt");
const y = [Link]("hoverPara");

[Link]("click", RespondClick);
[Link]("mouseover", RespondMouseOver);
[Link]("mouseout", RespondMouseOut);

function RespondMouseOver() {
[Link]("effect").innerHTML +=
"MouseOver Event" + "<br>";
}

function RespondMouseOut() {
[Link]("effect").innerHTML +=
"MouseOut Event" + "<br>";
}

function RespondClick() {
[Link]("effect").innerHTML +=
"Click Event" + "<br>";
}
</script>
</body>

</html>
Output:

Event Bubbling
Event bubbling is a method of event propagation in the HTML DOM API when an event is in an element inside
another element, and both elements have registered a handle to that event. It is a process that starts with
the element that triggered the event and then bubbles up to the containing elements in the hierarchy. In
event bubbling, the event is first captured and handled by the innermost element and then propagated to
outer elements.

Syntax:
addEventListener(type, listener, useCapture)
 type: Use to refer to the type of event.
 listener: Function we want to call when the event of the specified type occurs.
 userCapture: Boolean value. Boolean value indicates event phase. By Default useCapture is false. It means it is in the
bubbling phase.
Example 1: This example shows the working of event bubbling in JavaScript.

<!DOCTYPE html>
<html>

<head>
<title>
Bubbling Event in Javascript
</title>
</head>

<body>

<h2>Bubbling Event in Javascript</h2>

<div id="parent">
<button>
<h2>Parent</h2>
</button>
<button id="child">

<p>Child</p>

</button>
</div><br>

<script>
[Link](
"child").addEventListener("click", function () {
alert("You clicked the Child element!");
}, false);

[Link](
"parent").addEventListener("click", function () {
alert("You clicked the parent element!");
}, false);
</script>
</body>

</html>
Output:

After clicking on the Parent button:

After clicking on the Child button:

From above example we understand that in bubbling the innermost element’s event is handled first and then
the outer: the <p> element’s click event is handled first, then the <div> element’s click event.

Event Delegation
In this article, we'll explore the concept of event delegation in JavaScript, a powerful technique that allows you
to manage events efficiently, especially when dealing with a large number of similar elements, such as
buttons or list items.

What is Event Delegation?

Event delegation is a technique where you add a single event listener to a parent element instead of adding
multiple event listeners to each child element. This takes advantage of event bubbling, where an event
triggered on a child element propagates (or "bubbles up") to its parent elements. By placing the event
listener on a common ancestor, you can capture events from all its children.

Problem Scenario

Let's say we have a group of buttons, and we want to change the color of a button when it's clicked. Instead of
attaching a separate event listener to each button, we can attach one event listener to the parent element
that contains all the buttons. This is especially useful if we have a large number of buttons or if the buttons
are dynamically added to the DOM.

Example Implementation

Consider the following HTML structure:


const customUI = [Link]('ul');

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


const newElement = [Link]('li');
[Link] = "This is line " + i;
[Link]('click', () => {
[Link]('Responding')
})
[Link](newElement);
}

The above code will associate the function with every <li> element that is shown in the below image. We are
creating an <ul> element, attaching too many <li> elements, and attaching an event listener with a
responding function to each paragraph as we create it.
Implementing the same functionalities with an alternate approach. In this approach, we will associate the same
function with all event listeners. We are creating too many responding functions (that all actually do the
exact same thing). We could extract this function and just reference the function instead of creating too
many functions:
const customUI = [Link]('ul');

function responding() {
[Link]('Responding')
}

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


const newElement = [Link]('li');
[Link] = "This is line " + i;
[Link]('click', responding)
[Link](newElement);
}

The functionality of the above code is shown below –

In the above approach, we still have too many event listeners pointing to the same function. Now implementing
the same functionalities using a single function and single event.
const customUI = [Link]('ul');

function responding() {
[Link]('Responding')
}
for (var i = 1; i <= 10; i++) {
const newElement = [Link]('li');
[Link] = "This is line " + i;
[Link](newElement);
}
[Link]('click', responding)

Now there is a single event listener and a single responding function. In the above-shown method, we have
improved the performance, but we have lost access to individual <li> elements so to resolve this issue, we
will use a technique called event delegation.

The event object has a special property call .target which will help us in getting access to individual <li> elements
with the help of phases.

Steps:
 <ul> element is clicked.
 The event goes in the capturing phase.
 It reaches the target (<li> in our case).
 It switches to the bubbling phase.
 When it hits the <ul> element, it runs the event listener.
 Inside the listener function [Link] is the element that was clicked.
 [Link] provides us access to the <li> element that was clicked.
The .nodeName property of the .target allows us to identify a specific node. If our parent element contains more
than one child element then we can identify specific elements by using the .nodeName property.
const customUI = [Link]('ul');

function responding(evt) {
if ([Link] === 'li')
[Link]('Responding')
}

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


const newElement = [Link]('li');
[Link] = "This is line " + i;
[Link](newElement);
}

[Link]('click', responding);

How It Works

1. Parent Element Selection: We first select the parent element (buttonContainer) that contains all the buttons.
2. Event Listener: We attach an event listener to this parent element that listens for click events.
3. Event Bubbling: When any button inside the buttonContainer is clicked, the event bubbles up to the parent element.
The [Link] property is used to identify the specific child element (button) that was clicked.
4. Event Handling: Inside the event handler, we check if the clicked element is a button. If it is, we can proceed to perform
actions based on the button's inner text (e.g., changing the button's background color).

Advantages of Event Delegation

1. Efficiency: Instead of adding multiple event listeners to each child element, we only add one to the parent. This reduces
memory usage and enhances performance, especially when dealing with many elements.
2. Dynamic Content: If new buttons are added to the DOM dynamically, they will automatically be covered by the parent’s
event listener, without the need to add additional listeners.
3. Maintainability: The code is easier to maintain since there’s only one event listener to manage, rather than many.

Conclusion

Event delegation is a simple yet powerful technique that allows you to manage events efficiently in JavaScript. By
understanding and utilizing event bubbling and delegation, you can write cleaner, more efficient, and more
maintainable code. This approach is particularly useful when dealing with dynamic content or a large
number of similar elements.

Whether you are building a simple web application or a complex dynamic interface, mastering event delegation
will make your JavaScript code more robust and easier to manage.

Creating HTML with Javascript

In this article, we will discuss how to create HTML elements using JavaScript.

The following HTML has been provided to us, and our task is to recreate the given card element using JavaScript.

<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Creating HTML Element with JS</title>
<style>
#parent-container {
display: flex;
flex-direction: row;
}

.card-container {
width: 30%;
display: flex;
flex-direction: column;
text-align: center;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
margin: 10px;
padding-bottom: 5px;
}

@media only screen and (max-width: 600px) {


#parent-container {
flex-direction: column;
}
}
</style>
</head>

<body>
<div id="parent-container">
<div class="card-container">
<img class="image" src="[Link]
%20Survey%20Finds%2070%20Percent%20of%20Travelers%20plan%20to%20Holiday%20in%[Link]" alt="travel-card" />
<span>The journey of a thousand miles begins with a single
step</span>
</div>
</div>

<script src="[Link]"></script>
</body>

</html>

Output:
Rendered HTML

To re-create the card, we would first fetch the parent-container, by using [Link](), then we
would use the [Link] method to create a new element and set the CSS classes for that
element using the .[Link]() method.

Then, we would create another element - the image element with correct alt text(using setAttribute) and the
span with the text, and finally add child elements to parent elements using the .appendChild() method.

Check out the JS code enclosed in the script tag below -

<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Creating HTML Element with JS</title>

<style>
#parent-container {
display: flex;
flex-direction: row;
}
.card-container {
width: 30%;
display: flex;
flex-direction: column;
text-align: center;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
margin: 10px;
padding-bottom: 5px;
}

@media only screen and (max-width: 600px) {


#parent-container {
flex-direction: column;
}
}
</style>
</head>

<body>
<div id="parent-container">
<div class="card-container">
<img src="[Link]
%2070%20Percent%20of%20Travelers%20plan%20to%20Holiday%20in%[Link]" alt="travel-card" />
<span>The journey of a thousand miles begins with a single
step</span>
</div>
</div>

<script type="text/javascript">
const parentContainer = [Link]("parent-container");

const cardContainer = [Link]("div");


[Link]("card-container");

const cardImage = [Link]("img");


[Link]("src", "[Link]
%20Survey%20Finds%2070%20Percent%20of%20Travelers%20plan%20to%20Holiday%20in%[Link]");
[Link]('alt', "travel-card");

const cardSpan = [Link]("span");


const text = [Link]("The journey of a thousand miles begins with a single step");
[Link](text);

[Link](cardImage);
[Link](cardSpan);

[Link](cardContainer);
</script>
</body>

</html>

Output:
New element made with JS identical to the one made with HTML

Introduction to BOM & Difference between BOM and DOM

Understanding BOM and DOM in JavaScript: Key Differences and


Concepts
In this article, we will explore the concepts of BOM (Browser Object Model) and DOM (Document Object Model),
two fundamental JavaScript models, and the key differences between them. These models are essential for
interacting with web pages and browsers, and understanding them will enhance your ability to work with
JavaScript in a browser environment.

What is BOM (Browser Object Model)?


BOM stands for Browser Object Model, and it represents the browser's environment. BOM provides the
necessary tools to interact with various browser features and functionalities, such as browser information,
location, history, and more. It helps you interact with the browser itself, not just the web page content.
Why do we need BOM?
BOM allows us to access important information about the browser, and manipulate the browser window and
navigation. For example, you can:

 Find out which browser the user is using.


 Redirect users to specific pages.
 Access the browser’s history or location.

Some Key Objects in BOM:


 Window Object: Represents the browser window. It provides methods like alert(), open(), close(),
etc., to interact with the window.
 Navigator Object: Provides information about the browser, such as its version and name.
 Screen Object: Gives information about the screen size and resolution.
 History Object: Allows you to interact with the browser’s history, like navigating back or forward.
 Location Object: Used for accessing and manipulating the URL of the browser window.
These objects have various properties and methods that you can use to make decisions or control how the
browser behaves.

What is DOM (Document Object Model)?


DOM, or Document Object Model, represents the structure of a web page in a tree-like structure, where each
element is a node. It is used to represent the content of a webpage, and it allows you to access, modify, or
manipulate that content. With DOM, you can:

 Modify the HTML structure of the webpage.


 Change styles and appearance.
 Add or remove HTML elements dynamically.

Conclusion
With BOM, you can control the environment around your webpage, and with DOM, you can control the content
within your webpage. Together, they enable developers to create rich and interactive web experiences.

The window Object

Understanding the Window Object in JavaScript


The window object is an integral part of web development, providing a global interface for interacting with the
browser. It is part of the Browser Object Model (BOM) and offers numerous properties, methods, and
events that allow developers to access and manipulate the browser window.

What is the Window Object?


The window object is a global object provided by browsers. Being global means it can be accessed from
anywhere in your JavaScript code, whether inside or outside functions. Any variable or function declared
globally becomes part of the window object.

Key features of the window object:

 Global Scope: Variables or functions declared in the global scope automatically become properties of
the window object.
 Browser Information: Provides details like URL, history, screen size, and user agent.
 Utility Functions: Includes methods like alert(), setTimeout(), and [Link]().

Key Properties and Methods of the Window Object


Global Variables and Functions

Any global variable or function becomes a property of the window object. For example:
var yourName = "I don't Know!";
[Link]([Link]); // Outputs: I don't Know!

This allows you to access the variable anywhere in your code.

Alert, Confirm, and Prompt

alert(): Displays a message to the user. Example:


function showAlert(){
alert("Anything!");
}

confirm(): Displays a dialog box with OK and Cancel options. Returns true for OK and false for Cancel. Example:
function showConfirm(){
const result = confirm("Do you like JavaScript?");
[Link](result); // true or false
}

prompt(): Allows user input via a dialog box. Example:


funtion showPrompt(){
let age = prompt("What is your age?");
[Link](age);
}

Browser Information
location: Provides information about the current URL and allows redirection.
[Link]([Link]); // Outputs the current URL
[Link] = "[Link] // Redirects to Google

history: Enables navigation through browser history.


[Link](); // Navigates to the previous page
[Link](); // Navigates to the next page

navigator: Provides browser and user agent information.


[Link]([Link]); // Outputs the user agent string
[Link]([Link]); // Checks if the user is online

Screen Information

The screen object provides details about the user’s screen.

Example:
[Link]([Link]); // Screen width
[Link]([Link]); // Screen height

Visualizing the Window Object


Below is a simplified representation of how the window object organizes its properties and methods:

Window Object

|-- Document

|-- Location

|-- History

|-- Screen

|-- Navigator

|-- Console

|-- Timers (setTimeout, setInterval)

|-- Dialogs (alert, confirm, prompt)

Conclusion
The window object is a vital part of JavaScript, providing access to browser-related functionalities.
Understanding its properties and methods enables developers to create interactive, dynamic, and user-
friendly web applications. Practice using the window object in real-world scenarios to master its capabilities

SetTimeout,SetInterval and clearInterval clearTimeout

Understanding setTimeout, setInterval, clearTimeout, and


clearInterval in JavaScript and ReactJS
JavaScript provides powerful tools for executing code after a delay or repeatedly at set intervals. These include
the setTimeout, setInterval, clearTimeout, and clearInterval methods. Understanding these methods and
their practical use cases can greatly enhance your ability to manage time-based operations in your
applications.

What is setTimeout?
The setTimeout method allows you to execute a function after a specified time. This time is provided in
milliseconds.

Syntax:
setTimeout(callbackFunction, delayInMilliseconds);

Example:
function greet()
{
[Link]("Good Morning!");
}
setTimeout(greet, 2000); // Executes the greet function after 2 seconds

Use Case: You can use setTimeout for delayed operations, such as showing a popup or performing a background
task.

What is setInterval?
The setInterval method allows you to repeatedly execute a function at specified intervals. The interval is defined
in milliseconds.

Syntax:
setInterval(callbackFunction, intervalInMilliseconds);
Example:

let value = 0function counting()value += 1 { [Link]({counter : value}); }setInterval(counting, 1000);

Output:
{counter : 1}
{counter : 2}
{counter : 3}
{counter : 4}
and so on

Use Case: Use setInterval for periodic tasks, such as updating a clock or fetching data at regular intervals.

Clearing Timers
Sometimes, you may need to stop a timer before it completes its execution. JavaScript provides methods for this
purpose:

clearTimeout:

Stops a timeout set by setTimeout.

Example:
const timeoutId = setTimeout(() => {
[Link]("This won't execute");}, 2000);
clearTimeout(timeoutId); // Cancels the timeout

clearInterval:

Stops an interval set by setInterval.

Example:
let counter = 0;
const intervalId = setInterval(() => {
counter++;
[Link]();
if (counter === 5)
{
clearInterval(intervalId); // Stops the interval after 5 iterations }
}, 1000);

Conclusion
The setTimeout and setInterval methods, along with their clearing counterparts, are essential tools for managing
time-based operations in JavaScript. Use setTimeout for one-time delayed tasks and setInterval for recurring
tasks. Remember to clear these timers using clearTimeout or clearInterval when necessary to avoid
unexpected behavior or memory leaks.
polyfills for Map

In the ever-evolving world of web development, ensuring that your code works seamlessly across all browsers is
crucial. One challenge developers often face is the lack of support for modern JavaScript features in older
browsers. This is where polyfills come into play. In this article, we'll explore what polyfills are, why they are
essential, and how to create a polyfill for the map() method in JavaScript.

What is a Polyfill?
A polyfill is a piece of JavaScript code that enables modern functionalities on older browsers that do not natively
support them. As JavaScript evolves, new methods and features are introduced, but not all browsers,
especially older ones, support these updates. Polyfills serve as a fallback, allowing developers to implement
these new features even in environments where they are not supported.

The Need for Polyfills


Web applications are expected to function flawlessly across different browsers and versions. However, with the
rapid advancement of JavaScript, newer methods like map(), filter(), reduce(), and flatten() may not be
supported in older browsers. Without polyfills, using these methods could lead to functionality issues for
users on outdated browsers. Polyfills ensure that your code remains compatible and functional across all
platforms.

Creating a Polyfill for the map() Method


To understand how polyfills work, let's create a polyfill for the map() method. The map() method is used to apply
a function to each element in an array, returning a new array with the results.

Step 1: Understanding the Prototype

In JavaScript, every object has a hidden property called a prototype. This prototype can reference other objects
and contains methods that are shared across all instances of that object. For example, array methods
like map(), filter(), and reduce() are part of the [Link], allowing them to be used by any array.

Step 2: Writing the Polyfill

To create our own version of the map() method, we first need to extend the [Link] with our custom
method:

[Link] = function(callback) {
let tempArray = [];
for (let i = 0; i < [Link]; i++) {
[Link](callback(this[i], i, this));
}
return tempArray;
};

Explanation of the Code:

 [Link]: This extends the array prototype with a new method called myMap.
 callback: The myMap method takes a callback function as an argument. This callback will be applied
to each element in the array.
 this: In the context of the myMap method, this refers to the array on which myMap was called.
 tempArray: We create a temporary array to store the results of applying the callback function to
each element.
 for loop: The loop iterates over each element in the array, applying the callback function, and
pushing the result to tempArray.
 return tempArray: Finally, the method returns the new array containing the results.

Step 3: Using the Polyfill

Once the polyfill is in place, you can use myMap just like the built-in map() method:

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


const squaredArray = [Link](num => num ** 2);
[Link](squaredArray); // Output: [1, 4, 9, 16, 25]
This polyfill ensures that even if map() is not supported in an older browser, your code can fall back
on myMap() to achieve the same functionality.

Conclusion
Polyfills are a powerful tool for maintaining cross-browser compatibility in web applications. By creating polyfills
for modern JavaScript methods, you can ensure that your applications work seamlessly across all browsers,
regardless of their version. The example of the map() polyfill demonstrates how you can implement your
own versions of modern features to support older browsers.

the filter Method?


The filter method is a built-in array method in JavaScript that allows you to create a new array with all
elements that pass a test implemented by the provided function. Essentially, it filters out elements based on
a given condition.

let arr = [1, 2, 3, 4, 5, 6];


let result = [Link](number => number > 3);
[Link](result); // Output: [4, 5, 6]
In the above example, the filter method iterates over the array and returns a new array containing only the
elements greater than 3.

Creating a Polyfill for the filter Method


To create a polyfill for the filter method, we need to understand its core functionality. The method iterates
over an array, applies a test function to each element, and returns a new array containing only the elements
that pass the test.

Step-by-Step Process

1. Initialize a Temporary Array:


1. We start by initializing an empty array where the filtered elements will be stored.
2. Loop Through the Array:
1. Use a for loop to iterate through the array elements.
3. Apply the Condition:
1. For each element, apply the condition provided in the callback function. If the condition is
true, push the element into the temporary array.
4. Return the Result:
1. After the loop, return the temporary array containing all elements that passed the condition.

Implementing the Polyfill

Here’s how you can implement a basic polyfill for the filter method:

[Link] = function(callback) {
let tempArray = [];
for (let i = 0; i < [Link]; i++) {
if (callback(this[i], i, this)) {
[Link](this[i]);
}
}
return tempArray;
};

Output

[ 2, 4 ]

Explanation:

 Prototype Extension: We extend the Array prototype with a new method called myFilter.
 Callback Function: The callback function is invoked for each element in the array. It takes three
arguments: the current element, the index of the element, and the array itself.
 Condition Check: The condition is applied, and if true, the element is pushed into the tempArray.
Usage:

let arr = [1, 2, 3, 4, 5, 6];


let result = [Link](number => number > 3);
[Link](result); // Output: [4, 5, 6]

Advanced Implementation
To handle cases where additional parameters like the index and the array need to be passed, we can modify
our polyfill using function borrowing:

[Link] = function(callback) {
let tempArray = [];
for (let i = 0; i < [Link]; i++) {
if ([Link](this, this[i], i, this)) {
[Link](this[i]);
}
}
return tempArray;
};
Key Points:

 Function Borrowing: We use [Link](this, this[i], i, this) to invoke the callback in the context of the
array, passing the current element, its index, and the array itself.
 Return Value: The polyfill works the same as the native filter method, returning a new array with the
elements that pass the condition.

Conclusion
Creating polyfills is an essential skill for ensuring that your JavaScript code is robust and compatible across
different environments. The filter method is just one example of how you can implement a polyfill to mimic
the functionality of modern JavaScript features in older browsers.

Polyfills for Reduce

In JavaScript, the reduce() method is a powerful tool often used to accumulate values in an array into a single
result. Unlike map() and filter(), which return arrays, reduce() returns a single value. Due to its complexity and
importance, the polyfill for reduce() is a common topic in technical interviews. Understanding how to write
this polyfill will not only prepare you for interviews but also deepen your grasp of JavaScript's functional
programming.
Understanding the reduce() Method
Before diving into the polyfill, let's explore how the reduce() method works. Consider the following example
where we calculate the sum of all numbers in an array:
const arr = [1, 2, 3, 4, 5, 6];
const total = [Link]((acc, current) => acc + current, 0);
[Link](total); // Output: 21

Here’s how reduce() works:

 Accumulator (acc): This parameter holds the accumulated result of the function.
 Current Value (current): This parameter is the current element being processed in the array.
 Initial Value: The initial value of the accumulator. If not provided, the first element of the array is
used, and the iteration starts from the second element.
If an initial value is provided, the accumulator starts with this value, and the current value starts from the first
element.

Writing a Polyfill for reduce()


Let's write a polyfill for reduce() from scratch. We will implement a custom version called myReduce().

Step 1: Define the Polyfill Structure

First, we add the myReduce method to [Link] so it becomes available to all arrays:

[Link] = function(callback, initialValue) {


let accumulator = initialValue !== undefined ? initialValue : this[0];
let startIndex = initialValue !== undefined ? 0 : 1;

for (let i = startIndex; i < [Link]; i++) {


accumulator = [Link](undefined, accumulator, this[i], i, this);
}

return accumulator;
};

Step 2: Explanation of the Code

1. Initial Setup:
o Accumulator: If initialValue is provided, it is assigned to accumulator; otherwise, the first
element of the array is used.
o Start Index: If initialValue is provided, the iteration starts from index 0; otherwise, it starts
from 1.
2. Looping Through the Array:
oThe loop iterates over the array starting from startIndex. For each element, the callback
function is called with the accumulator, the current element, the current index, and the
entire array as arguments.
o The result of the callback is assigned back to accumulator.
3. Returning the Result:
o After the loop completes, the final value of accumulator is returned.

Step 3: Handling Edge Cases

To make the polyfill robust, you should handle edge cases, such as:

 Non-function Callbacks: Ensure the callback passed is a function.


 Non-array Objects: Ensure that myReduce() is called on an array.

[Link] = function(callback, initialValue) {


if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}

if (![Link](this)) {
throw new TypeError('Object is not an array');
}

let accumulator = initialValue !== undefined ? initialValue : this[0];


let startIndex = initialValue !== undefined ? 0 : 1;

for (let i = startIndex; i < [Link]; i++) {


accumulator = [Link](undefined, accumulator, this[i], i, this);
}

return accumulator;
};

Step 4: Testing the Polyfill

Let's test our myReduce() method to ensure it works as expected:


const arr = [1, 2, 3, 4, 5, 6];
const total = [Link]((acc, current) => acc + current, 0);
[Link](total); // Output: 21

By changing the initial value or the callback logic, you can perform different accumulations, such as product
calculation or finding the maximum value in an array.

Conclusion
The reduce() method is a cornerstone of functional programming in JavaScript. Writing a polyfill for reduce() not
only prepares you for technical interviews but also solidifies your understanding of JavaScript's array
methods and functional programming concepts. By handling edge cases and ensuring robust error checking,
you can create a professional-grade polyfill that showcases your attention to detail and depth of knowledge.

polyfills for flatten

One of the frequently asked interview questions in JavaScript is how to flatten an array. Flattening an array
means converting a nested array into a single-dimensional array, removing all subarrays and nesting. This
concept is essential, especially when dealing with complex data structures. JavaScript provides a built-in
method called flat() to achieve this, but in an interview, you might be asked to implement this functionality
yourself, which is where writing a polyfill comes into play.

What Does Flattening an Array Mean?


Consider the following array:
const arr = [1, 2, 3, 4, [5, 6], [[7, 8]]];

Flattening this array would result in:


// Output: [1, 2, 3, 4, 5, 6, 7, 8]

The goal is to transform the nested structure into a single-level array. JavaScript’s flat() method does this up to a
specified depth.

Using the flat() Method

The flat() method is simple to use:


const result = [Link]();
[Link](result); // Output: [1, 2, 3, 4, 5, 6, [7, 8]]

By default, flat() only flattens the array one level deep. To flatten deeper levels, you can specify the depth as an
argument:
const result = [Link](2);
[Link](result); // Output: [1, 2, 3, 4, 5, 6, 7, 8]

For arrays with unknown levels of nesting, you can use Infinity:
const result = [Link](Infinity);
[Link](result); // Output: [1, 2, 3, 4, 5, 6, 7, 8]

Writing a Polyfill for flat()


Now, let’s create our own version of the flat() method—a polyfill. This will help you understand how flat() works
under the hood and prepare you for similar interview challenges.
Step 1: Set Up the Polyfill Structure

We start by extending the [Link] with a new method called myFlat:

[Link] = function(depth = 1) {
const tempArray = [];

function flatten(arr, depth) {


for (let element of arr) {
if ([Link](element) && depth > 0) {
flatten(element, depth - 1);
} else {
[Link](element);
}
}
}

flatten(this, depth);
return tempArray;
};

Explanation of the Code:

 [Link]: Adds a new method to all array instances.


 depth: The number of levels to flatten. By default, it is set to 1.
 tempArray: A temporary array that will hold the flattened result.
 flatten(): A recursive function that checks each element of the array. If the element is an array and
the depth is greater than 0, it recursively calls itself with a decremented depth. Otherwise, it pushes
the element into the tempArray.

Step 2: Testing the Polyfill

Now, let’s test our myFlat method:


const arr = [1, 2, 3, 4, [5, 6], [[7, 8]]];
const result = [Link](2);
[Link](result); // Output: [1, 2, 3, 4, 5, 6, 7, 8]

This test shows that our polyfill correctly flattens the array up to the specified depth.

How the Polyfill Works


1. Initialization: We define a tempArray to store the flattened elements.
2. Recursive Flattening: The flatten() function is called recursively. It iterates through the array and
checks if each element is an array. If it is, and if the depth allows, it calls itself recursively with the
nested array and a decremented depth.
3. Adding Non-Array Elements: If the element is not an array or the depth limit has been reached, the
element is pushed into tempArray.
4. Return the Flattened Array: Finally, after all elements have been processed, tempArray is returned as
the flattened array.

Conclusion
Flattening arrays is a common operation in JavaScript, and understanding how to implement this functionality
from scratch can significantly deepen your knowledge of recursion, array methods, and JavaScript in
general. Writing polyfills like myFlat prepares you for technical interviews and gives you a solid grasp of
JavaScript’s core features.

As you continue to explore polyfills, challenge yourself by implementing others like slice(), splice(), and more.
Each polyfill you write will strengthen your understanding of JavaScript and prepare you for a wide range of
coding scenarios.

Polyfills - Call and Apply

JavaScript offers a powerful feature called "function borrowing," which allows one object to use a method
belonging to another object. This is often achieved through the call, apply, and bind methods. These methods
enable explicit binding of this to a function, making them crucial for flexible function execution. In this
article, we will explore how to write polyfills for these methods, which is a common topic in technical
interviews.

Function Borrowing and Explicit Binding


Function borrowing refers to the ability of an object to borrow a method from another object and use it as if it
were its own. The methods call, apply, and bind facilitate this borrowing by explicitly binding the this keyword
to a specific object. Here’s a quick refresher on how each method works:

 call(): Invokes a function, allowing you to pass in arguments one by one.


 apply(): Similar to call(), but arguments are passed as an array.
 bind(): Creates a new function that, when invoked, has its this keyword set to the provided value, with a given sequence
of arguments preceding any provided when the new function is called.
Now, let's delve into writing polyfills for call, apply, and bind.

Polyfill for call()

The call() method allows you to invoke a function and explicitly set this to the provided object. Here's how you
can create a polyfill for call():

[Link] = function(context, ...args) {


if (typeof this !== 'function') {
throw new TypeError('myCall must be called on a function');
}
context = context || window;
const fnSymbol = Symbol();
context[fnSymbol] = this;
const result = context[fnSymbol](...args);
delete context[fnSymbol];
return result;
};

Explanation:

 Context Binding: The function (this) is temporarily added as a method to the context object.
 Unique Property: A unique symbol is used to avoid overwriting existing properties on the context object.
 Invocation: The function is called with the provided arguments.
 Cleanup: The temporary property is deleted from the context object to restore its original state.

Polyfill for apply()

The apply() method is similar to call(), but it takes arguments as an array. Here’s the polyfill for apply():

[Link] = function(context, args) {


if (typeof this !== 'function') {
throw new TypeError('myApply must be called on a function');
}
context = context || window;
const fnSymbol = Symbol();
context[fnSymbol] = this;
const result = context[fnSymbol](...(args || [])); // Spread the array of arguments
delete context[fnSymbol];
return result;
};

Explanation:

 Arguments Handling: The args array is spread into individual arguments when invoking the function.
 Similar Structure: The structure is almost identical to myCall, with the primary difference being how arguments are
handled.

Polyfill for bind()

The bind() method returns a new function with this bound to a specified object. Here’s how to create a polyfill
for bind():

[Link] = function(context, ...args) {


if (typeof this !== 'function') {
throw new TypeError('myBind must be called on a function');
}
const self = this;
return function(...newArgs) {
return [Link](context, [...args, ...newArgs]); // Combine pre-set args with new args
};
};

Explanation:

 Function Closure: myBind returns a new function that remembers the original function ( self) and the
context.
 Argument Combination: The arguments passed during the binding (args) are combined with the
arguments provided during the function's invocation (newArgs).

Handling Edge Cases

For robustness, it's essential to include edge case handling, such as ensuring that myCall, myApply,
and myBind are called on functions and that the context provided is an object. This enhances the reliability of
the polyfill in different scenarios.

Conclusion

Writing polyfills for call, apply, and bind not only deepens your understanding of how JavaScript handles
function context but also prepares you for challenging technical interviews. By mastering these polyfills, you
gain insight into the inner workings of JavaScript's function borrowing and explicit binding mechanisms,
which are foundational to advanced JavaScript development.

Polyfills - bind

In the previous lesson, we discussed polyfills for the call() and apply() methods in JavaScript. Now, let's dive
into the polyfill for the bind() method, which works a bit differently from call() and apply().
Unlike call() and apply(), which invoke a function immediately, bind() returns a new function that can be
invoked later. This distinction makes the bind() method unique and useful in various scenarios. In this article,
we will explore how to create a polyfill for the bind() method and understand its inner workings.

What is the bind() Method?


The bind() method creates a new function that, when invoked, has its this keyword set to a specified value,
along with a given sequence of arguments preceding any provided when the new function is invoked. It does
not immediately call the function but instead returns a function that can be executed later.

Example:
const user = {
name: 'Prakash',
city: 'Mumbai'
};

function displayUserInfo(state) {
[Link](`Hi, I am ${[Link]} from ${[Link]}, ${state}.`);
}

const boundFunction = [Link](user, 'Maharashtra');


boundFunction(); // Output: Hi, I am Prakash from Mumbai, Maharashtra.

In this example, the bind() method is used to bind the user object to the displayUserInfo function, along with
the argument 'Maharashtra'. The returned boundFunction can be invoked later, retaining the context and
arguments passed during the binding.

Creating a Polyfill for bind()


Now, let's create a polyfill for the bind() method. A polyfill is a piece of code that replicates the functionality
of a newer feature in older environments where it is not supported natively.

Step 1: Define the Polyfill Function

First, we extend the [Link] with our custom myBind method:

[Link] = function(context, ...args) {


const func = this;
return function(...rest) {
return [Link](context, [...args, ...rest]);
};
};

Explanation of the Code:

 [Link]: This extends the [Link] with a new method called myBind.
 context: The context parameter is the object to which this should refer when the new function is
called.
 args: The rest parameter (...args) captures any additional arguments passed during the binding
process.
 func: The this keyword inside myBind refers to the function on which myBind is called. We store this
function in the func variable.
 return function: myBind returns a new function that, when invoked, calls the original function ( func)
with the specified context and arguments.
 apply(): Inside the returned function, apply() is used to call the original function with the combined
arguments (...args and ...rest).
Step 2: Testing the Polyfill

Let's test our myBind polyfill to ensure it works as expected:

const user = {
name: 'Prakash',
city: 'Mumbai'
};

function displayUserInfo(state) {
[Link](`Hi, I am ${[Link]} from ${[Link]}, ${state}.`);
}

const boundFunction = [Link](user, 'Maharashtra');


boundFunction(); // Output: Hi, I am Prakash from Mumbai, Maharashtra.
This test confirms that our myBind polyfill successfully replicates the functionality of the
native bind() method.

Understanding the Execution Flow


1. Context Binding: The context (in this case, the user object) is passed to the myBind method, which
sets this inside the returned function to refer to user.
2. Argument Handling: The initial arguments (...args) are captured during the binding. When the
returned function is invoked later, any additional arguments ( ...rest) are combined with the initial
ones.
3. Function Invocation: The original function (displayUserInfo) is called using apply() with the bound
context and combined arguments.

Conclusion
The bind() method is a powerful tool in JavaScript, allowing developers to create functions with a
predetermined this context and initial arguments. By creating a polyfill for bind(), we've ensured that this
functionality is available even in environments where the native bind() method may not be supported.

Understanding how to implement polyfills not only helps in writing backward-compatible code but also
deepens your understanding of how JavaScript functions operate under the hood. The concepts learned
here are valuable for both improving your JavaScript skills and preparing for technical interviews, where
polyfills are a common topic.

Callback functions
A callback function is a function that is passed as an argument to another function and is invoked or called by
that function at a certain point in time. The main purpose of a callback function is to allow asynchronous
processing or non-blocking behavior in programming languages that support it. Callback functions are
commonly used in event handling, such as when responding to user actions or when performing operations
that require significant time to complete. They are also used in higher-order functions that take other
functions as arguments, such as map(), filter(), and reduce() function in JavaScript.

let us try to understand with the help of the example

function outer(wrapper){
[Link]("Outer function is called");
wrapper();
}
function callback(){
[Link]("function b is called");
}
outer(callback);

Output

Outer function is called


function b is called

It is important to remember that the execution of the callback function depends upon the execution of the
function, which the callback is passed to.

Let us understand how callback functions are useful for async Programming.

Take an example of setTimeout method - It is a method used to execute a piece of code after a certain
delay.

[Link]("hello");
setTimeout(function callback(){
[Link]("Delayed by 4 seconds ");

},4000)

Output

hello
Delayed by 4 seconds

Here the callback function passed to setTimeout executes after a delay of 4 seconds hence it is useful in async
Programming.

Another example of a callback function could be the use case of fetch.

fetch('[Link]
.then(response => [Link]())
.catch(error => [Link](error));

Here we are making a network call to fetch some data from the JSON placeholder and we are waiting for the
response to come back, once we receive the response our callback function is executed which is passed as
an argument to the then method. In case Our response fails, our callback function for the catch method is
called.
Without the concepts of Callback Functions ,async Programming could not be possible.

How async Js Works ?

JavaScript is a Single-threaded Synchronous language by single Threaded means that the js engine has a single
thread to execute instructions. By synchronous, it means that the js engine executes code line by line (one
line at a time).

What is Async Programming?


Async programming is a programming model that allows code to run asynchronously or non-blocking. This
means that while a task is being executed, other code can continue to run concurrently without waiting for
the task to complete.

So how does async behavior is achieved by JavaScript?


It is important to understand that the js engine only has a single call stack to execute js code but it still
manages to make async programming work like fetching data from a server, calling set timeout, providing
timer, local Storage, etc. So How do JS engines execute all that?
The ability of js to execute async tasks like calling an API, doing [Link], and manipulating dom events is
not part of the js engine but it is provided by the browser where the js engine executes javascript code. Let's
look at the image below to understand what all functionalities the browser provides to the js Engine.
The timer is provided by the browser which allows the power to execute methods like setTimeout and
setInterval that allow certain delays in the set timeout call.

All the dom-related methods to access and attach event listeners on certain nodes are also provided by
Browser to the js engine.
Even the most famous console is not part of the js engine but is part of web-api provided by the browser.

Let us now try to understand how async code gets executed.

Example -1

[Link]("Line1");
setTimeout(function callback1(){
[Link]("Line3");

},3000);
[Link]("Line6");
Output

Line1
Line2
Line3

To understand how this code works out we need to understand the event loop and callback queue

Event Loop
In JavaScript, an event loop is a mechanism that enables asynchronous programming. The event loop works
by continuously processing a queue of events and executing any associated callbacks or functions.

Callback Queue
In JavaScript, the callback queue is a mechanism used by the event loop to manage asynchronous code
execution. Whenever an asynchronous operation is performed, such as a timer set by setTimeout() or an
HTTP request made by fetch(), the associated callback function is added to the callback queue.

The event loop constantly monitors the callback queue and executes the callbacks in the order in which they
were added, one at a time. This ensures that the JavaScript runtime remains single-threaded and that no
two callbacks are executed simultaneously.

Explanation For the code example above

first, line1 is executed and it simply prints [Link]("line1") then as soon as js engines encounter
setTimeout it sets a timer in the web API and the call stack gets empty then line 6 gets executed due to
javascript synchronous and non-blocking nature. Once the timer is expired in the web-API it registers and
passes the callback function in the callback queue also at the same time event loop is continuously
monitoring the call stack whether it is empty or not, once it sees the call stack as empty it pushes the
callback method in the call stack and then callback function gets executed and it prints to
[Link]("line6");

Example 2

[Link]("lets Start"); // line1


const btnAddtoCart = [Link]("btn"); //line2
[Link]("click",()=> { //line3
[Link]("Button Clicked");
});
[Link]("Bye Bye ......");
Let us try to understand the execution of the code above line by line.

Initially, the line1 [Link]("Let Start") is printed then js engine moves to the next line and extracts the
node from the DOM and saves its reference in a variable called btnAddtoCart.
Then as soon it encounters line 3, event listener is registered in the web-API and the js engine moves
forward and prints the last line [Link]("Bye Bye ").
Once a user clicks on the button to which the event listener is attached, the callback is pushed into the
callback queue, and once the event loop finds the call stack as empty callback queue pushes the callback
function into the call stack, and the function gets executed.
So the output of the above will always be:
"lets Start"
"Bye Bye ....."
"Button Clicked"

Here is the image of the Event loop and callback queue

We have an important point to understand in case we have both the setTimeout and Promise callbacks in
our code then whose Callback will be executed first?

The callback queue is the queue which is also known by the name task Queue but we also have a queue
named microTask queue.
All the promised-based callbacks are registered inside the microtask queue and have the highest priority and
all the other types of callback are pushed into the callback queue or the task queue as it have less priority
then the microtask queue.

Callback hell
In JavaScript, the scenario where the code becomes densely nested and challenging to read due to the overuse
of callbacks is referred to as "callback hell." When using asynchronous actions, like network requests or file
operations, where the code must wait for a response before continuing, this can happen. It can be difficult
to handle the code and to keep track of the execution flow when several callbacks are chained together and
nested inside one another. For developers, this can result in bugs, mistakes, and a great deal of stress.

let us try to understand this by considering this scenario - :

On a hotel booking website, the general flow to booking a hotel is this - :


First API is called to book a hotel then an API is called to Proceed To Payment then after that, an API is called
to showBookingStatus then internally an API is called to updateBookingHistory at the server side. Now let's
try to implement this in a piece of code

bookHotel(hotelId,function(){
if(err){
errorHandler();
}else{
proceedToPayment(hotelId,function(){
if(err){
erroHandler();
}else{
showBookingStatus(hotelId,function(){
if(err){
errorHandler();
}else{
updateBookingHistroy(hotelId,function(){
success();
})
}
})
}
})
}
})

Now we are calling an API called book hotel and depending upon the response we are calling another API known
as proceedToPayment depending upon the result of the previous API we are calling another API.
So this creates two problems-
1 Pyramid Of Doom
2 Inversion of Control

If you take a look at the above code it is clear that our code is expanding in the horizontal direction instead
of the vertical direction which is considered a bad practice in programming as it makes the code less
readable and difficult to identify bugs as well.

The second Problem with this callback style of Programming is the inversion of control, the callback
function's actual control is given to the function that it is being passed as an argument into so suppose our
API gets into the ideal State i.e we get no response from the server our callback function will never be
executed

Promises in Javascript

A promise in JavaScript represents the eventual outcome of an asynchronous operation and its value, whether
successful or failed. Promises are commonly used to handle various asynchronous tasks such as fetching
data from an API, reading files, or waiting for a timer to expire.

Consider Promise as a special Object in Javascript which has different states and corresponding different values
of each state.
A promise is initially in a pending state and changes to either a "Fulfilled" or "rejected" state depending on
whether the promise was resolved or rejected. Initially, the value of the promise is undefined and changes
to the value of the resolve(value) method if the promise is successful or changes to an error in case the
reject(error) method is called.
Look at this diagram to understand it in a better way.

Now let us Understand How can we consume promises?


In case we are fetching data from an API using the fetch method which returns a promise we need to
consume it to read the actual response from the server. let us look at the example of a fetch call and how
can we consume a promise returned by Fetch().

let promise1 = fetch('[Link]


[Link](function(response){
return [Link]();
}).then(function(commits){
alert(commits[0].[Link])
}).catch(function(error){
alert("Some Error in fetching response")
});

In the code above we have special methods then and catch which are used to consume promises. we attach
then method to the promise and pass a callback function to then method which will be executed once the
promise is successfully resolved in case the promise is rejected catch method callback function gets
executed and displays the appropriate response.
It is important to remember that each call on then method also returns the promise whose fulfilled value is
equal to the value returned by the callback function inside then method.

Creating a Promise and Method Chaining

In this article, we will learn how can we create our own Promise.

We use new Promise Constructor Syntax to create a new Promise -

let promise = new Promise(function(resolve, reject) {


// executor
});

The executor is the function that is provided to the new Promise. When a new Promise is created, the
executor is executed automatically. The callbacks, resolve, and reject, are provided by JavaScript itself, and
our code is only contained within the executor. Regardless of whether the result is obtained soon or late,
the executor must call either the resolve(value) callback, indicating successful completion of the job along
with the result value, or the reject(error) callback, indicating an error object if an error occurred.

let us try to understand this with the help of an example


const isRequestSuccessfull = true;

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


if(isRequestSuccessfull){
resolve("promise resolved");
}else{
const error = new Error("Something Went Wrong");
reject([Link]);
}
});

[Link](promise);

Output

Promise { 'promise resolved' }

As in the above code, the executor function runs immediately and calls resolve inside the if [Link] the value
of isRequestSuccessfull is false then it would have called reject and with the promise state as Rejected. Now
let us see how can we consume our promise code using the then and catch method.

See the code below

const isRequestSuccessfull = true;

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


if(isRequestSuccessfull){
resolve("promise resolved");
}else{
const error = new Error("Something Went Wrong");
reject([Link]);
}
});

[Link](response=>[Link](response))
.catch(err=>[Link](err));

Output

promise resolved

It is important to remember that in case the executor calls the resolve method, the value of the
response parameter in the callback of then method will always be equal to the value passed in as the
argument while calling the resolve method resolve(value). So then method is used to handle successful
responses generally, although it is also capable of handling the reject response as well.

Now let us see what happens in case the promise is Rejected.


const isRequestSuccessfull = false;

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


if(isRequestSuccessfull){
resolve("promise resolved");
}else{
const error = new Error("Something Went Wrong");
reject([Link]);
}
});

[Link](response=>[Link](response))
.catch(err=>[Link](err));

Output

Something Went Wrong

Here we can see that the output is "Something Went Wrong" because the promise was rejected catch method
callback was fired and the value of the err is equal to the argument passed into the reject() method inside
the executor function.

Now let us see how can we handle multiple chaining using then method.

Promise Chaining: Promise Chaining is a simple concept by which we may initialize another promise inside
our .then() method and accordingly we may execute our results. The function inside then captures the value
returned by the previous promise

The syntax for using promise chaining is as follows.

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


resolve("Hello JavaScript");
});

promise
.then( function (result1){
[Link](result1);
return new Promise((resolve,reject) =>{
resolve("GFG is awesome");
})
})
.then((result2) => {
[Link](result2);
});
Output

Hello JavaScript
GFG is awesome

Lets see another example:

function asyncOperation(value) {
return new Promise((resolve, reject) => {
// Simulating an asynchronous operation
setTimeout(() => {
const result = value * 2;
resolve(result);
}, 1000);
});
}

// Chain multiple 'then' methods


asyncOperation(3)
.then(result1 => {
[Link](`Step 1: ${result1}`);
return result1 + 5;
})
.then(result2 => {
[Link](`Step 2: ${result2}`);
return result2 * 3;
})
.then(finalResult => {
[Link](`Final Result: ${finalResult}`);
})
.catch(error => {
[Link](`Error: ${error}`);
});

Output:

Step 1: 5

Step 2: 0

Final Result: 0

Promise API'S - [Link](), [Link](), [Link]() v/s [Link]()


The Promise API comprises a collection of JavaScript functionalities that facilitate the handling of asynchronous
code in a more graceful and comprehensible manner. Essentially, a Promise is an object that denotes a value
that might not be accessible immediately but will be resolved eventually.
We will cover [Link]() ,[Link](), [Link]() v/s [Link]() in this article .

[Link]()

Consider a scenario where we have to execute multiple promises in parallel and wait until all of them are
ready. For instance, download several URLs in parallel and process the content once they are all done.

The syntax is:


let promise = [Link]();
Let us Try to Understand this with an example.

let promise1 = new Promise(resolve => setTimeout(() => resolve(1), 3000));


let promise2 = new Promise(resolve => setTimeout(() => resolve(2), 2000)); // 2
let promise3 = new Promise(resolve => setTimeout(() => resolve(3), 1000)); // 3

let finalPromise = [Link]([promise1,promise2,promise3]);


[Link](res=>[Link](res)).catch(err=>[Link](err));

Output

[ 1, 2, 3 ]

Here You can see that the result Promise gives an array consisting of resolved promises value.

Please note that the order of the resulting array members is the same as in its source promises. Even though
the first promise takes the longest time to resolve, it’s still first in the array of results.
It is important to observe that the sequence of elements in the resulting array corresponds to that of the
source promises. This implies that although the initial promise may take the most time to resolve, it will still
be the first member in the outcome array.

let us Look at another example in which we are fetching different url of different GitHub profiles.

const urls = [
'[Link]
'[Link]
];
const requests = [Link](url => fetch(url));
[Link](requests)
.then(responses => [Link](
response => [Link](`${[Link]}: ${[Link]}`)
)).catch(err => [Link]([Link]));

The output of the above code will be


[Link] 200
[Link] 200

[Link]()

[Link] rejects as a whole if any promise rejects. That’s good for “all or nothing” cases when we need all
results successful to [Link] just waits for all promises to settle, regardless of the result.
The resulting array will be -
{status: "fulfilled", value: result} for successful responses
{status: "rejected", reason: error} for errors

look at the code below to understand better.

let urls = [
'[Link]
'[Link]
'[Link]
];
[Link]([Link](url => fetch(url)))
.then(results => { // (*)
[Link]((result, num) => {
if ([Link] == "fulfilled") {
[Link](`${urls[num]}: ${[Link]}`);
}
if ([Link] == "rejected") {
[Link](`${urls[num]}: ${[Link]}`);
}
});
});

The output of the above code will be


[
{status: 'fulfilled', value: ...response...},
{status: 'fulfilled', value: ...response...},
{status: 'rejected', reason: ...error object...}
]
We can see even when the third promise is rejected the overall result of the promise is not rejected but it
gives the successful response of the first two promises and only shows rejected for the promise that was
rejected unlike [Link] .

[Link]()
This function is like [Link], but instead of waiting for all promises to settle, it only waits for the first one
to settle and retrieves its result or error.

[Link]([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(res => [Link](res)) // 1

Since the initial promise was the quickest to settle, it became the final outcome. Once the first promise is
settled and emerges as the winner, any subsequent results or errors are disregarded.

[Link]()

[Link]([
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 1000)),
new Promise((resolve, reject) => setTimeout(() => resolve(1), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(res=>[Link](res)); // 1

Although the initial promise was the quickest, it was rejected, and as a result, the second promise became
the outcome. Once the first promise that was fulfilled wins the race, any additional outcomes are
disregarded.

So What is the difference between Promise. any and promise. race ?


Here's an example: imagine you have three promises that represent different tasks you want to do
simultaneously. Promise 1 represents checking your email, Promise 2 represents making a phone call, and
Promise 3 represents sending a text message.

If you use [Link](), the method will return the result of the first promise that finishes, whether it was
successful or not. So, if Promise 1 finishes first but it's a rejection (e.g., you couldn't log in to your email), the
[Link]() method will immediately return the rejection value without waiting for Promise 2 or Promise
3 to finish.

If you use [Link](), the method will return the first promise that finishes successfully (i.e., it gets resolved).
So, if Promise 2 finishes first and it's successful (e.g., you finished your phone call), Promise. any() will return
that result and Promise 1 and Promise 3 will stop executing. However, if none of the promises get resolved
and they all reject, then [Link]() will throw an error.

Prototype
In JavaScript, every object has an internal and hidden property called [[Prototype]], which is either null or
references another object. This property allows JavaScript to implement a feature known as "prototypal
inheritance." Understanding prototypes is crucial for grasping how JavaScript objects inherit properties and
methods.

What is a Prototype?
A prototype in JavaScript is a special hidden property of an object. This property either holds a reference to
another object (the prototype) or is null. The object referenced by the prototype is used to provide
inheritance. For example, methods and properties defined on a prototype can be accessed by all objects
that inherit from that prototype.

Consider the following example:

let user = {
name: "Prakash",
role: "mentor"
};

[Link](user);
When you log the user object, you can see its properties ( name and role). However, there's also a
hidden [[Prototype]] property, which you can see by expanding the object in a browser's developer console.

Accessing Prototype Methods


The prototype object contains methods and properties that can be accessed by the object itself. For example,
JavaScript objects have a toString method, which is available through the prototype:
[Link]([Link]()); // Outputs: [object Object]

Even though toString is not directly defined in the user object, JavaScript looks for it in the object's prototype and
executes it. This behavior is due to prototypal inheritance, where an object tries to access a property or
method. If it's not found within the object itself, JavaScript looks up the prototype chain to find it.

Creating Custom Prototypes


You can also create your own prototypes to define custom behaviors for your objects. Here's an example:

const admin = {
isAdmin: true
};
let user = {
name: "Prakash",
role: "mentor",
__proto__: admin
};

[Link]([Link]); // Outputs: true


In this example, we create an admin object with a property isAdmin. We then set the __proto__ of the user object
to admin, which means the user object now inherits from admin. As a result, [Link] returns true.

Prototype Chaining
Prototypes in JavaScript can be chained, allowing objects to inherit from multiple prototypes. For instance:

const loggedInStatus = {
isLoggedIn: true
};

admin.__proto__ = loggedInStatus;

[Link]([Link]); // Outputs: true


Here, we added another level of prototype chaining by setting admin's prototype to loggedInStatus. Now,
the user object can access properties from both admin and loggedInStatus through prototype chaining.

Overriding Prototype Methods


If an object defines a method or property that is also defined in its prototype, the object's method or property
will override the prototype's. For example:

[Link] = function() {
[Link]("Hello, User!");
};

[Link] = function() {
[Link]("User is an admin.");
};

[Link](); // Outputs: "Hello, User!"


In this example, even though admin has a showMessage method, the user object's own showMessage method
takes precedence.

Accessing Prototype Properties and Methods


You can access an object's own properties using [Link](), but this method only returns properties directly on
the object, not those inherited from the prototype:
[Link]([Link](user)); // Outputs: ["name", "role"]

To access all properties, including those from the prototype, you can use a for...in loop:
for (let key in user) {
[Link](key); // Outputs: "name", "role", "isAdmin", "isLoggedIn"
}

Conclusion
Prototypes are a powerful feature in JavaScript that enable objects to share and inherit properties and methods.
By understanding how prototypes work, you can leverage inheritance and method overriding to write more
flexible and reusable code.

While prototypes are foundational in JavaScript, their use is often abstracted away by higher-level constructs like
classes. However, having a solid grasp of how prototypes work under the hood will make you a more
proficient JavaScript developer.

Basics of Classes

Object-Oriented Programming (OOP) is a programming paradigm that relies on the concept of classes and
objects. It's a powerful tool for organizing and structuring your code in a way that models real-world entities
and relationships. In this article, we’ll delve into the basics of OOP by exploring classes and objects in
JavaScript, providing a strong foundation for more advanced topics like inheritance and encapsulation.

What is a Class?
In simple terms, a class is a blueprint for creating objects. Think of it as a template that defines the structure and
behavior of objects. For instance, if you were to design a series of mobile phones, you would start with a
single blueprint that specifies the design and features. From this blueprint, you can manufacture as many
phones as you want, each with the same specifications. Similarly, in programming, a class allows you to
define a template for objects.

Example: Creating a User Class


Let's consider a real-world scenario where you need to manage data for students in a school. You want to store
their names, roles, login status, and whether they have administrative privileges. Instead of manually
creating an object for each student, you can define a User class that serves as a blueprint for all student
objects.

Here’s how you can define a basic User class in JavaScript:


class User {
constructor(name, role, isAdmin, isLoggedIn) {
[Link] = name;
[Link] = role;
[Link] = isAdmin;
[Link] = isLoggedIn;
}
}
In this example, the constructor method is used to initialize the properties of the class. These properties
include name, role, isAdmin, and isLoggedIn. When you create a new User object, you provide these values as
arguments.

Creating Objects from a Class


Using the User class, you can now create multiple objects, each representing a different student:

const user1 = new User('Prakash', 'Mentor', false, true);


const user2 = new User('Ashish', 'Mentor', false, true);
const user3 = new User('Sakshi', 'Mentor', false, true);

[Link](user1); // Output: User {name: 'Prakash', role: 'Mentor', isAdmin: false, isLoggedIn: true}
[Link](user2); // Output: User {name: 'Ashish', role: 'Mentor', isAdmin: false, isLoggedIn: true}
[Link](user3); // Output: User {name: 'Sakshi', role: 'Mentor', isAdmin: false, isLoggedIn: true}
Each object—user1, user2, and user3—is an instance of the User class, containing its own set of properties based
on the values passed to the constructor.

Adding Methods to a Class


Classes can also have methods that define the behavior of the objects created from the class. For example, you
might want to display the information of each user:

class User {
constructor(name, role, isAdmin, isLoggedIn) {
[Link] = name;
[Link] = role;
[Link] = isAdmin;
[Link] = isLoggedIn;
}

displayInfo() {
[Link](`${[Link]} is a ${[Link]}`);
}
}

[Link](); // Output: Prakash is a Mentor


[Link](); // Output: Ashish is a Mentor
[Link](); // Output: Sakshi is a Mentor
The displayInfo method uses the this keyword to access the properties of the object. It logs a message to the
console that includes the user's name and role.

Understanding the Prototype


In JavaScript, methods defined in a class are not directly stored in the objects themselves. Instead, they are
stored in the object’s prototype. When you call a method on an object, JavaScript looks for that method in
the object's prototype chain.
[Link]([Link](user1)); // Output: User {constructor: ƒ, displayInfo: ƒ}

The displayInfo method is part of the prototype, not the individual User objects. This is an efficient way to handle
methods, as they don’t need to be duplicated across multiple objects.

How Classes Work Under the Hood


When a class is declared in JavaScript, it effectively creates a function. The constructor function, which initializes
the properties of the class, becomes the body of this function. When you use the new keyword to create an
instance of the class, JavaScript constructs an object that includes the properties defined in the constructor
and links it to the prototype, where methods are stored.

Conclusion

Understanding classes and objects is fundamental to mastering Object-Oriented Programming in JavaScript. A


class acts as a blueprint, allowing you to create multiple objects with the same structure and behavior. By
defining methods within a class, you can encapsulate functionality that applies to all objects created from
that class. As you continue to explore OOP, you’ll discover more advanced concepts like inheritance and
encapsulation, which further enhance your ability to write organized and efficient code.

In the next lesson, we’ll dive into inheritance, a powerful feature that allows one class to inherit properties and
methods from another. This will open the door to more complex and dynamic object-oriented programming
in JavaScript.

Classes Inheritance

Inheritance is a fundamental concept in object-oriented programming (OOP), allowing one class to inherit
properties and methods from another class. This mechanism promotes code reuse and enhances the
organization of your code by establishing relationships between classes. In this article, we'll explore the
concept of class inheritance in JavaScript and how it can be used to create more structured and
maintainable code.

What is Inheritance?
Inheritance, in the context of programming, is the process by which one class (known as the child or subclass)
acquires the properties and behaviors (methods) of another class (known as the parent or superclass). This
is similar to the way in which children inherit traits from their parents. In programming, inheritance allows a
subclass to inherit features from a superclass, thus enabling code reuse and a hierarchical relationship
between classes.

Basic Example: Laptop and Specific Brands


Let's consider a real-world example where we have a generic Laptop class that contains common properties
like RAM, Processor, and Generation. Specific laptop brands like Dell and Lenovo can then inherit these
properties from the Laptop class, adding their unique attributes as needed.

Here's how you can define the Laptop class:

class Laptop {
constructor(ram, processor, generation) {
[Link] = ram;
[Link] = processor;
[Link] = generation;
}

displaySpecs() {
[Link](`Laptop Specs: RAM = ${[Link]}, Processor = ${[Link]}, Generation = ${[Link]}`);
}
}
In this example, the Laptop class has a constructor that initializes the ram, processor, and generation properties. It
also has a method displaySpecs that logs these specifications to the console.

Creating a Subclass with Inheritance


Now, let's say we want to create a Dell class that represents a specific brand of laptops. Instead of redefining
the ram, processor, and generation properties in the Dell class, we can simply inherit these from
the Laptop class using the extends keyword.

class Dell extends Laptop {


constructor(ram, processor, generation, modelName, price) {
super(ram, processor, generation); // Call the parent class's constructor
[Link] = modelName;
[Link] = price;
}
displaySpecs() {
[Link](); // Call the parent class's displaySpecs method
[Link](`Model Name = ${[Link]}, Price = ${[Link]}`);
}
}
Here, the Dell class extends the Laptop class, meaning it inherits all the properties and methods from
the Laptop class. The constructor method in Dell uses the super keyword to call the parent class's constructor,
ensuring that ram, processor, and generation are properly initialized. The Dell class also adds two new
properties: modelName and price.

Creating Instances and Accessing Methods


Let's create an instance of the Dell class and see how inheritance works in practice:
const dellLaptop = new Dell('8GB', 'Intel i5', '10th Gen', 'Dell Latitude', 45000);
[Link]();

When you run this code, the following output will be displayed:
Laptop Specs: RAM = 8GB, Processor = Intel i5, Generation = 10th Gen
Model Name = Dell Latitude, Price = 45000

Here’s what’s happening:

 The Dell class inherits the displaySpecs method from the Laptop class and extends it to
include modelName and price.
 The super keyword is used to call the parent class's methods and constructors, ensuring that the
properties defined in Laptop are correctly initialized in the Dell subclass.

Adding More Subclasses


The beauty of inheritance is that it allows for easy expansion. Suppose you want to create another subclass for a
different brand, such as Lenovo. You can do this by simply extending the Laptop class, just as we did with
the Dell class:

class Lenovo extends Laptop {


constructor(ram, processor, generation, modelName, price) {
super(ram, processor, generation);
[Link] = modelName;
[Link] = price;
}

displaySpecs() {
[Link]();
[Link](`Model Name = ${[Link]}, Price = ${[Link]}`);
}
}

const lenovoLaptop = new Lenovo('16GB', 'AMD Ryzen 7', '5th Gen', 'Lenovo ThinkPad', 60000);
[Link]();
This code will output:
Laptop Specs: RAM = 16GB, Processor = AMD Ryzen 7, Generation = 5th Gen
Model Name = Lenovo ThinkPad, Price = 60000

Understanding the super Keyword

The super keyword plays a crucial role in class inheritance:

 Calling the Parent Constructor: When used inside a subclass constructor, super() calls the parent
class's constructor, allowing the subclass to inherit and initialize properties defined in the parent
class.
 Calling Parent Methods: The super keyword can also be used to call methods from the parent class
within the subclass, enabling the subclass to build upon or override these methods.

Conclusion
Class inheritance is a powerful feature in JavaScript that allows developers to create hierarchical relationships
between classes, promoting code reuse and reducing redundancy. By using the extends keyword and
the super function, subclasses can inherit properties and methods from parent classes, while also adding
their unique characteristics. This not only makes your code more organized and maintainable but also
closely mirrors real-world relationships and hierarchies.

In future lessons, we'll explore more advanced concepts like method overriding, multiple inheritance, and how
inheritance interacts with JavaScript's prototype-based inheritance model. Understanding these concepts
will further enhance your ability to write robust and scalable JavaScript applications.

Static Properties and Methods

In JavaScript, classes can have special types of methods and properties known as "static methods" and "static
properties." These are distinct from regular methods and properties because they are associated with the
class itself rather than with instances (objects) created from the class. Let’s explore what these are and how
they can be used.

What are Static Methods?


Static methods are functions defined on the class itself, rather than on instances of the class. This means that
you can call a static method directly on the class, without having to instantiate an object from the class.

Example:
class Children {
constructor(name, age) {
[Link] = name;
[Link] = age;
}

static sortByAge(child1, child2) {


return [Link] - [Link];
}
}

let child1 = new Children("Prakash", 11);


let child2 = new Children("Ashish", 19);
let child3 = new Children("Ria", 9);

let childrenArray = [child1, child2, child3];


[Link]([Link]);

[Link](childrenArray);
In this example, sortByAge is a static method that sorts an array of Children objects by their age. Since sortByAge is
static, it's called on the Children class itself, not on an instance of Children.

Why Use Static Methods?


Static methods are useful when you want to perform operations that are related to the class, but not to any
specific object of that class. For example, if you want to perform operations on a collection of objects or
need utility functions related to the class, static methods are the right choice.

What are Static Properties?


Static properties are variables that are attached to the class itself rather than to objects created from the class.
This means all instances of the class share the same static property.

Example:

class Children {
static ID = 1;

constructor(name, age) {
[Link] = name;
[Link] = age;
[Link] = [Link]++;
}
}

let child1 = new Children("Prakash", 11);


let child2 = new Children("Ashish", 19);
let child3 = new Children("Ria", 9);
[Link]([Link]); // Outputs: 1
[Link]([Link]); // Outputs: 2
[Link]([Link]); // Outputs: 3
In this example, ID is a static property. It is used to assign a unique ID to each child object. Each time a
new Children object is created, the ID property is incremented.

Accessing Static Properties and Methods


To access a static method or property, you use the class name itself, not an instance of the class:
[Link]([Link]); // Accessing the static property
[Link](child1, child2); // Accessing the static method

Use Cases for Static Methods and Properties


1. Utility Functions: Static methods are perfect for utility functions that apply to the entire class, such as sorting or
searching through a collection of objects.
2. Counters: Static properties can be used to keep track of data across all instances, like assigning unique IDs to objects or
counting how many instances of the class have been created.
3. Configuration Constants: You can use static properties to store configuration values that are the same across all
instances of the class.

Practical Example
Let’s consider a scenario where you need to find all children above a certain age:

class Children {
static ID = 1;

constructor(name, age) {
[Link] = name;
[Link] = age;
[Link] = [Link]++;
}

static filterByAge(childrenArray, ageLimit) {


return [Link](child => [Link] > ageLimit);
}
}

let child1 = new Children("Prakash", 11);


let child2 = new Children("Ashish", 19);
let child3 = new Children("Ria", 9);

let olderChildren = [Link]([child1, child2, child3], 10);

[Link](olderChildren); // Outputs: child1 and child2


Output

[
Children { name: 'Prakash', age: 11, id: 1 },
Children { name: 'Ashish', age: 19, id: 2 }
]

Here, filterByAge is a static method that filters and returns an array of Children objects that are older than a
specified age.

Conclusion
Static methods and properties are powerful tools in JavaScript that allow you to create methods and properties
that are tied to the class itself, rather than to instances of the class. They are particularly useful for utility
functions, shared counters, and configuration constants. Understanding how to effectively use static
methods and properties can help you write more efficient and organized code.

Private Properties

In modern JavaScript development, controlling access to certain properties within a class is crucial for
maintaining the integrity and security of your code. This is where private properties come into play. Private
properties are those that cannot be accessed or modified from outside the class, thus ensuring that certain
data remains protected and only modified in a controlled manner. In this article, we'll explore how to create
and use private properties in JavaScript, including the latest syntax additions and their implications.

What Are Private Properties?


Private properties are variables that are meant to be inaccessible from outside the class in which they are
defined. They help enforce encapsulation—a core principle in object-oriented programming (OOP)—by
restricting direct access to certain data within a class. This ensures that the data is only accessible through
controlled methods, reducing the risk of unintended side effects from direct modifications.

Creating a Private Property in JavaScript


To illustrate private properties, let's consider a simple User class where each user has a unique ID. We want to
ensure that this ID cannot be changed directly from outside the class.

Here's how you might define the User class with a public property:
class User {
constructor(id) {
[Link] = id; // Public property
}
}

const user = new User('123');


[Link]([Link]); // Output: 123

[Link] = '321';
[Link]([Link]); // Output: 321 (ID has been changed externally)
In the example above, the id property is public, meaning it can be accessed and modified directly from outside
the class. This could lead to potential issues if the ID is inadvertently changed.

To convert this into a private property, you can use the new private field syntax by adding a # before the
property name:

class User {
#id; // Private property

constructor(id) {
this.#id = id;
}

// Method to access the private ID


getId() {
return this.#id;
}

// Method to change the private ID


changeId(newId) {
this.#id = newId;
}
}

const user = new User('123');


[Link]([Link]()); // Output: 123

// Attempting to access or modify the private property directly will result in an error
user.#id = '321'; // SyntaxError: Private field '#id' must be declared in an enclosing class

// Changing the ID through the class method


[Link]('321');
[Link]([Link]()); // Output: 321

Key Features of Private Properties:


1. Private Fields Syntax: The # symbol is used before the property name to declare it as private. This is
a recent addition to JavaScript and ensures that the property is only accessible within the class.
2. Encapsulation: By using private properties, you ensure that critical data cannot be altered from
outside the class. This makes your code more robust and secure.
3. Controlled Access: You can provide controlled access to private properties through methods defined
within the class, as shown with the getId and changeId methods in the example.

Limitations and Browser Support


While private properties add a valuable layer of protection, they come with some limitations:

 Not Yet Universally Supported: The private fields syntax (#) is a relatively new feature and may not
be supported in all JavaScript environments, especially older browsers. Developers might need to use
polyfills or transpilers like Babel to ensure compatibility.
 No Access Outside the Class: Once a property is marked as private using #, it cannot be accessed or
modified outside the class by any means, making it a strictly controlled entity.

Conclusion
Private properties in JavaScript provide a powerful way to enforce encapsulation and protect your data from
unintended external modifications. By using the # syntax, you can easily declare private properties within
your classes and control their accessibility through class methods. As this feature continues to gain support
across browsers and environments, it will become an essential tool in every JavaScript developer's toolkit.

Incorporating private properties into your code is a step toward writing more secure, maintainable, and
predictable applications. So, start experimenting with private properties in your projects, and enjoy the
benefits of encapsulated, clean code!

Key Features of Private Properties:


1.
Private Fields Syntax: The # symbol is used before the property name to declare it as private. This is a
recent addition to JavaScript and ensures that the property is only accessible within the class.
2.
3.
Encapsulation: By using private properties, you ensure that critical data cannot be altered from outside
the class. This makes your code more robust and secure.
4.
5.
Controlled Access: You can provide controlled access to private properties through methods defined
within the class, as shown with the getId and changeId methods in the example.
6.

Limitations and Browser Support


While private properties add a valuable layer of protection, they come with some limitations:
 Not Yet Universally Supported: The private fields syntax (#) is a relatively new feature and may not
be supported in all JavaScript environments, especially older browsers. Developers might need to use
polyfills or transpilers like Babel to ensure compatibility.
 No Access Outside the Class: Once a property is marked as private using #, it cannot be accessed or
modified outside the class by any means, making it a strictly controlled entity.

Conclusion
Private properties in JavaScript provide a powerful way to enforce encapsulation and protect your data from
unintended external modifications. By using the # syntax, you can easily declare private properties within
your classes and control their accessibility through class methods. As this feature continues to gain support
across browsers and environments, it will become an essential tool in every JavaScript developer's toolkit.

You might also like