My Java Script
My Java Script
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.
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
Syntax:
[Link](" ");
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.
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.
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.
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
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.
The const keyword is used to declare variables that are meant to be constants, meaning their values should not
change once assigned.
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.
Output
Hello, GeeksforGeeks!
JavaScript is awesome!
Error : Assignment to constant variable
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!
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.
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.
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.
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 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.
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.
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.
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.
Output
undefined
[Link]
The number data type is used to represent numeric values. In JavaScript, numbers can be integers or floating-
point (decimals).
Output
number
number
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.
boolean
If you try to use "true" or "false" in quotes, they will be treated as strings:
[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.
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 [].
Output
object
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:
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
Explanation
Multiline Example
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:
Output
Output
Output
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.
Example
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
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
For subtraction, multiplication, and division, JavaScript converts strings to numbers if possible.
Mixing Types
Output
123
9
36
4
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.
If you try to add these strings directly, JavaScript will concatenate them, resulting in "310" instead of the
numeric sum 13.
To achieve the desired numeric addition, you need to convert these strings to numbers using
the Number function:
const a = "3";
const b = "10";
const c = Number(a);
const d = Number(b);
Output
string
string
number
number
Output
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
Output
true
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:
if (!isNaN(number)) {
[Link](number + 8); // Outputs: 50
} else {
[Link]("Invalid input");
}
Output
50
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.
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
1. Set Up readline-sync:
const readlineSync = require('readline-sync');
2. Ask for User Input:
Let's extend this to ask the user for their age and calculate their birth year.
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.
To run this code, open your terminal, navigate to the directory containing your script, and use the following
command:
node [Link]
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.
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.
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:
Output
true
false
true
false
false
Explanation:
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:
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.
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:
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.
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.
JavaScript has special rules when comparing null and undefined. While they are loosely equal (==), they are not
strictly equal (===).
Code Example:
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).
null has unique behavior when used in mathematical comparisons (such as <, >, <=, >=). In these
comparisons, null is treated as 0.
Code Example:
Output
false
true
true
false
Explanation:
Let's put some of these comparisons to the test! Try predicting the output of the following comparisons.
Code Example:
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.
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:
if (isLoggedIn) {
[Link]("You are logged in.");
}
Output
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:
Output
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:
Output
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:
Output
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:
Explanation:
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:
Explanation:
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:
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.
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.
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.
Output
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."
[Link](totalMarks < 40 ? "You need to work hard." : "You cleared the exam.");
Output
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.
const result = totalMarks < 40 ? "You need to work hard." : "You cleared the exam.";
[Link](result);
Output
This way, the appropriate message is assigned to the variable result, which is then printed to the console.
You can also use nested ternary operators, but be cautious as it can make the code harder to read:
Output
In this example, the ternary operators are nested to determine the grade based on the score.
Output
A grade
We can achieve the same logic using a single line of code with ternary operators:
[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.
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 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.
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.
Output
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.
Output
In this example, the message "You are eligible for engineering." will be printed because the math score is greater
than 85.
Example:
const isStudentEligible = false;
if (!isStudentEligible) {
[Link]("You are not eligible.");
} else {
[Link]("You are eligible.");
}
Output
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.
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.
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.
In this expression:
Here, firstName is undefined, so the nullish coalescing operator assigns the default value "Hidden Geek".
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.
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.
In this case, OR considers the empty string as falsy, so it returns the fallback value "Hidden Geek".
Here, since firstName is an empty string (""), the nullish coalescing operator does not return "Hidden Geek",
because the value is neither null nor undefined.
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.
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.
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;
In this case, b is undefined. The nullish coalescing operator replaces it with 0, so the output is 12.
|| (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
}
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.
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
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
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);
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.
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.
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.
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.`);
}
Output
Multiple Parameters
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.
If you call a function without passing all the required arguments, the missing arguments will be undefined.
Exercise
Create a function calculateSum that accepts two parameters min and max, and returns the sum of all numbers
from min to max.
Output
55
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.
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.
Basic Syntax
The basic syntax for creating an anonymous function looks like this:
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.
To confirm that the variable holding the anonymous function is indeed a function, you can use
the typeof operator:
[Link](typeof greet); // Output: function
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.
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.
setTimeout(function() {
[Link]("This is a callback function!");
}, 1000);
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
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.
Arrow Function
[Link](square(5)); // Output: 25
If there are no parameters, empty parentheses are used:
function Person() {
[Link] = 0;
setInterval(() => {
[Link]++; // `this` refers to the Person object
[Link]([Link]);
}, 1000);
}
For simple conditional logic, ternary operators can be used to keep the arrow function concise.
Examples
[Link]("myButton").addEventListener("click", () => {
[Link]("Button clicked!");
});
2 Array Methods:
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.
When iterating over a string, you often need to perform tasks such as searching for a character, counting
occurrences, or manipulating individual characters.
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.
let count = 0;
The for...of loop is a cleaner and more readable way to iterate over the elements of an iterable object, such as a
string.
[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.
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.
Output
30
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]()
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';
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.
// Original string
var str = 'JavaScript is object oriented language';
Output
// 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.
function func() {
var str = 'ephemeral';
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.
function func() {
var str = 'ephemeral';
[Link](value);
}
func();
Output
NaN
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.
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.
// Original string
var str = 'Departed Train';
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.
// Original string
var str = 'Departed Train';
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.
// Original string
var str = 'Departed Train';
Output
-1
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:
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:
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:
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.
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.
Output
true
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
Using includes, you can create conditional checks without needing to compare values explicitly with true or false.
Example:
if ([Link]("light")) {
[Link]("Person loves to code in light mode.");
} else {
[Link]("Person loves to code in dark mode.");
}
Output
Combining multiple methods and conditions can lead to very powerful and flexible code.
Example:
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.
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.
[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.
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.
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.
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.
Output
geeksforgeeks
eksforgeeks
eksforgeeks
Output
prakashnar...
In responsive design, you might want to show a truncated version of text on smaller screens and the full
version on larger screens.
prakashnar...
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.
// Using substring
[Link]([Link](0, 10)); // Output: "prakashnar"
// Using slice
[Link]([Link](0, 10)); // Output: "prakashnar"
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.
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.
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.
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
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
[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
[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
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.
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 an Array
You can create an array using square brackets [] and separate items with commas:
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:
Array Methods
map
Creates a new array with the results of calling a function for every array element:
filter
Creates a new array with elements that pass a test provided by a function:
It is used to reduce the array into one single value using some functional logic
array = [ 1, 2, 3, 4, 5, 6 ];
[Link](array)
[Link](sum);
Output
[ 1, 2, 3, 4, 5, 6 ]
21
Using Some
[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.
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.
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.
Example:
function func() {
var arr = ['GFG', 'gfg', 'g4g'];
}
func();
Output
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.
Output:
7
34,234,567,4,jacob,true,23.45
Program 1:
function func() {
// Original array
var arr = [34, 234, 567, 4];
Output
7
[
34, 234, 567, 4,
23, 45, 56
]
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]()
Return value This method returns the removed element array. If the array is empty, then this function returns
undefined.
Example:
function func() {
var arr = ['GFG', 'gfg', 'g4g', 'GeeksforGeeks'];
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
Program 1:
function func() {
var arr = [34, 234, 567, 4];
Output
4
[ 34, 234, 567 ]
Program 2:
function func() {
var arr = [];
Output
undefined
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.
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
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]
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
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
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.
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:
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
Program 1:
Output
true
Program 2:
Output
false
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.
Program 1:
// Original string
var arr = ["Geeks", "for", "Geeks"]
[Link](arr);
// Sorting the array
[Link]([Link]());
}
func();
Output
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
Output
[ 1, 2, 4, 5, 8 ]
[ 1, 2, 4, 5, 8 ]
Program 2:
// 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).
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.
Example:
function func() {
//Original string
var str = 'Geeks for Geeks'
var array = [Link]("for");
[Link](array);
}
func();
Output
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]
Program 1:
function func() {
//Original string
var str = 'It iS a 5r&e@@t Day.'
var array = [Link](" ");
[Link](array);
}
func();
Output
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' ]
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;
}
inputString = "hello";
[Link](isPalindrome(inputString)); // false
Detailed Steps
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.
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
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
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
Output
12345
In this example, the array arr is unpacked, and each element is printed individually.
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.
You can also add elements in between or around the arrays while merging.
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.
Copying an Object
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1 };
[Link](obj2); // Output: { a: 1, b: 2 }
Output
{ a: 1, b: 2 }
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.
Output
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:
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
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
};
Output
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"
};
Output
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.
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.
Example:
[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.
[Link](firstName);//"alpha"
[Link](secondName);//"beta"
[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.
[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.
[Link](firstName);//"alpha"
[Link](lastName);//"gamma, delta"
Output
alpha
[ 'gamma', 'delta' ]
//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.
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
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
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
Example 9:
const user = {
name: 'John Doe',
age: 30
};
const { name, job = 'Unemployed' } = user;
[Link](name); // John Doe
[Link](job); // Unemployed
Example 10:
const 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.
Consider the following example where we create a copy of an array and then modify the copy
// Modify arr2
[Link](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.
The spread operator (...) is a convenient way to create a shallow copy of an array that points to a different
memory location.
Syntax:
Another way to create a copy is by manually iterating over the array and pushing elements to the new array.
// Modify arr5
[Link](4);
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.
4. Using concat
The concat method can be used to create a new array that includes the elements of the original array.
// Modify arr9
[Link](4);
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.
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,
...
}
const person = {
name: 'Prakash',
age: 99,
job: 'Mentor'
};
Here, we have created an object person with three properties: name, age, and job.
1. Dot Notation:
[Link] Notation:
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.
Deleting Properties
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
const userProfile = {
'first name': 'Jane',
'last name': 'Doe'
};
[Link](userProfile['first name']); // Output: Jane
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.
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.');
}
};
const obj = {
name: 'Prakash Sakari',
greetMessage() {
[Link]('Hello, Prakash! Welcome to GFG.');
}
};
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));
}
};
Output
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'
};
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.
const obj = {
name: 'Prakash',
age: 100
};
[Link](obj);
// Output: { name: 'Prakash', age: 100, city: 'Mumbai', state: 'Maharashtra' }
Output
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
};
[Link](obj);
// Output: { name: 'Prakash', age: 100, city: 'Mumbai', state: 'Maharashtra' }
Output
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.
Let's take an example where you get a key from the user and add that key to the object:
const obj = {
name: 'Prakash',
age: 100
};
[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'.
const obj = {
name: 'Prakash',
age: 100
};
const course = [Link]('Which course do you want to learn? (HTML, CSS, JS, React, Redux): ');
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.
Output
In the example above, we explicitly write the property names ( name and city) and their values
(name and city variables).
Output
Here, name and city are shorthand for name: name and city: city.
Let's define some variables and use them to create an object using shorthand properties:
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.
const obj = {
name: 'Prakash',
city: 'Mumbai'
};
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.
const person = {
name: 'Prakash',
city: 'Mumbai'
};
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.
We can enhance the previous example to show both keys and values in a formatted string.
const person = {
name: 'Prakash',
city: 'Mumbai'
};
Output
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:
const car = {
make: 'Tesla',
model: 'Model S',
year: 2020
};
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.
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:
const person1 = {
name: 'Prakash',
age: 101,
address: {
city: 'Mumbai',
state: 'Maharashtra'
}
};
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
const person1 = {
name: 'Prakash',
age: 101,
address: {
city: 'Mumbai',
state: 'Maharashtra'
}
};
Output
Prakash
Ashish
Mumbai
Sirsa
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'
}
};
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
};
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'
}
};
Output
Sirsa
Sirsa
Spread Operator
The spread operator (...) can also be used to create a shallow copy of an object:
const person1 = {
name: 'Prakash',
age: 101,
address: {
city: 'Mumbai',
state: 'Maharashtra'
}
};
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']
};
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'
};
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.
const userWithFunction = {
name: 'Prakash',
getDisplayMessage: function() {
[Link]('Welcome, Prakash');
}
};
const userWithoutFunction = {
name: 'Prakash'
};
userWithoutFunction?.getDisplayMessage?.(); // No output, no error
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
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
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:
Nested Destructuring
Renaming Variables
Destructuring Arrays
Basic Array Destructuring
Skipping Items
Exercises
To practice, create an object with nested properties and try to extract specific values using destructuring. For
example:
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
[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
[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
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
};
[Link](sum); // Output: 20
Output
20
const obj = {
name: 'Prakash',
age: 99,
city: 'Mumbai'
};
Output
true
true
false
You can use a for...in loop to iterate over the keys of an object:
const obj = {
name: 'Prakash',
age: 99,
city: 'Mumbai'
};
// 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:
"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.
Example:
const obj = {
name: "Prakash",
displayMessage: function() {
[Link](this);
}
};
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]);
}
};
Example:
function showThis() {
[Link](this);
}
Example:
const obj = {
name: "Prakash",
displayMessage: () => {
[Link]([Link]);
}
};
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();
}
};
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();
}
};
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:
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.
In the constructor function, properties are added to the object being created using the this keyword:
Prakash
25
You can use the constructor function to create multiple objects efficiently:
Output
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:
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.
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.
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.
[Link](user1, ['[Link] ECE', 2015]); // Output: Prakash, Degree: [Link] ECE, Year: 2015
[Link](user2, ['[Link] CS', 2018]); // Output: Ashish, Degree: [Link] CS, Year: 2018
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]}.`);
}
[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.
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);
Let's modify our sayHi function to take additional parameters and use bind to pass these arguments:
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.
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!
[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.
Modules allow you to split a large program into smaller, logically related files. For example:
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.
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.
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!
[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.
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.
In this file, we use require('./utils') to import the functions from the [Link] module. Once imported, we can call
these functions as needed.
// [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.
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:
[Link]('Hello, World!');
greetFunction();
Named Export:
[Link]('Hello, World!');
greet();
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.
loadMath();
await import() ensures the code waits for the module to load before using it.
Conditional Imports:
if (isMathRequired) {
[Link]([Link](4, 5));
Static Imports
Dynamic Imports
Loading Time
Loaded on-demand
Use Case
Syntax
await import('...')
Improved Performance:
Load only what is needed, reducing the overall bundle size.
Resource Efficiency:
Avoid unnecessary module loading for users who don’t require certain features.
Modular Codebase:
ReactJS Example
In a ReactJS application, dynamic imports are used for lazy loading components:
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
export default App;
Below is a diagram illustrating the difference between static and dynamic imports:
Static Import:
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.
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.
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.
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.
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
function foo() {
[Link]("Inside foo");
}
function bar() {
[Link]("Inside bar");
foo();
}
bar();
[Link]("Global Context End");
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
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: []
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.
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.
Execution Phase
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.
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).
After allocating memory, the code execution phase comes here the code inside the function executes, and
undefined is replaced by the actual value.
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 ;
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.
function showName() {
[Link]("My name is Prakash Sakari");
}
Even if we invoke the function before its declaration, it still works due to hoisting:
function showName() {
[Link]("My name is Prakash Sakari");
}
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.
Hoisting with let and const is different. They 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.
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.
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:
Debugger Example
{
// TDZ starts
[Link](x); // Throws ReferenceError
let x = 9; // TDZ ends
[Link](x); // Outputs: 9
}
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
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.
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.
function doubleValue(number) {
return number * 2;
}
const multiplier = 4;
function doubleValue(number) {
return number * multiplier;
}
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;
}
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;
}
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:
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.
Here, greetMessage is a variable that holds a function. When you call greetMessage(), it executes the function.
function wrapperFunction() {
return "Welcome to GeeksForGeeks!";
}
Output
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.
function greetMessage() {
return function() {
[Link]("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.
Here, greetMessage() is called first, which returns the inner function, and then the returned function is
immediately executed with the second pair of parentheses.
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:
function wrapper() {
return "Welcome to GFG";
}
function greetMessage(wrapper, name) {
[Link](`${name}, ${wrapper()}`);
}
function displayMessage() {
return function() {
[Link]("Hello from the inner function");
};
}
function calculatePower(power) {
return function(number) {
return [Link](number, power);
};
}
[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.
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 square(number) {
return number ** 2;
}
function cube(number) {
return number ** 3;
}
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() 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:
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);
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:
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:
Output
[ 2, 6, 4 ]
Syntax:
[Link](function_to_be_applied)
[Link](function (args) {
// condition;
})
Example:
[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;
}
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
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
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 :
hello(4);
Output
4
[Arguments] { '0': 4 }
[Arguments] { '0': 9 }
4
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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
The lexical environment is a theoretical concept that refers to the environment in which code is written and
executed. It includes:
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.
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.
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.
// Driver code
Output
15
Have a look at the image representation of every step of the function call .
Factorial of a number using recursion
// 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;
}
120
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.
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.
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.
function outerFunction() {
let outerVariable = 10;
function innerFunction() {
[Link](outerVariable); // Accesses outerVariable
}
return innerFunction;
}
Output
10
Explanation:
Closures in Action
function counter() {
let count = 0;
return function() {
count++;
return count;
};
}
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
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;
}
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.
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.
The creation of the DOM follows a specific process during the page load:
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.
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.
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.
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>
<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"
onclick="geeks()"
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>
<body style="text-align:center">
<h1>GeeksforGeeks</h1>
<h2>DOM getElementById() Method</h2>
<h3 id="geeks">Hello Geeks!</h3>
</html>
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">
</div>
<button onclick="myFunction()">Try 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>
<script>
// Get the button element by its ID
var button = [Link]("myButton");
var geek=[Link]("geek")
</script>
</body>
</html>
Output:
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>
<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>
<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:
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.
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
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')
}
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')
}
[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).
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.
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;
}
<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.
<!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;
}
<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");
[Link](cardImage);
[Link](cardSpan);
[Link](cardContainer);
</script>
</body>
</html>
Output:
New element made with JS identical to the one made with HTML
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.
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]().
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!
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
}
Browser Information
location: Provides information about the current URL and allows redirection.
[Link]([Link]); // Outputs the current URL
[Link] = "[Link] // Redirects to Google
Screen Information
Example:
[Link]([Link]); // Screen width
[Link]([Link]); // Screen height
Window Object
|-- Document
|-- Location
|-- History
|-- Screen
|-- Navigator
|-- Console
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
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:
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:
Example:
const timeoutId = setTimeout(() => {
[Link]("This won't execute");}, 2000);
clearTimeout(timeoutId); // Cancels the timeout
clearInterval:
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.
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.
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;
};
[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.
Once the polyfill is in place, you can use myMap just like the built-in map() method:
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.
Step-by-Step Process
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:
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.
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
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.
First, we add the myReduce method to [Link] so it becomes available to all arrays:
return accumulator;
};
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.
To make the polyfill robust, you should handle edge cases, such as:
if () {
throw new TypeError('Object is not an array');
}
return accumulator;
};
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.
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.
The goal is to transform the nested structure into a single-level array. JavaScript’s flat() method does this up to a
specified depth.
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]
[Link] = function(depth = 1) {
const tempArray = [];
flatten(this, depth);
return tempArray;
};
This test shows that our polyfill correctly flattens the array up to the specified depth.
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.
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.
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():
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.
The apply() method is similar to call(), but it takes arguments as an array. Here’s the polyfill for apply():
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.
The bind() method returns a new function with this bound to a specified object. Here’s how to create a polyfill
for bind():
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).
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.
Example:
const user = {
name: 'Prakash',
city: 'Mumbai'
};
function displayUserInfo(state) {
[Link](`Hi, I am ${[Link]} from ${[Link]}, ${state}.`);
}
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.
[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
const user = {
name: 'Prakash',
city: 'Mumbai'
};
function displayUserInfo(state) {
[Link](`Hi, I am ${[Link]} from ${[Link]}, ${state}.`);
}
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.
function outer(wrapper){
[Link]("Outer function is called");
wrapper();
}
function callback(){
[Link]("function b is called");
}
outer(callback);
Output
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.
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.
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).
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.
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.
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
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"
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.
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.
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.
In this article, we will learn how can we create our own Promise.
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.
[Link](promise);
Output
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.
[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.
[Link](response=>[Link](response))
.catch(err=>[Link](err));
Output
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
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
function asyncOperation(value) {
return new Promise((resolve, reject) => {
// Simulating an asynchronous operation
setTimeout(() => {
const result = value * 2;
resolve(result);
}, 1000);
});
}
Output:
Step 1: 5
Step 2: 0
Final Result: 0
[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.
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]));
[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
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]}`);
}
});
});
[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.
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.
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.
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.
const admin = {
isAdmin: true
};
let user = {
name: "Prakash",
role: "mentor",
__proto__: admin
};
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] = function() {
[Link]("Hello, User!");
};
[Link] = function() {
[Link]("User is an admin.");
};
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.
[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.
class User {
constructor(name, role, isAdmin, isLoggedIn) {
[Link] = name;
[Link] = role;
[Link] = isAdmin;
[Link] = isLoggedIn;
}
displayInfo() {
[Link](`${[Link]} is a ${[Link]}`);
}
}
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.
Conclusion
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.
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.
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
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.
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
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.
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.
Example:
class Children {
constructor(name, age) {
[Link] = name;
[Link] = age;
}
[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.
Example:
class Children {
static ID = 1;
constructor(name, age) {
[Link] = name;
[Link] = age;
[Link] = [Link]++;
}
}
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]++;
}
[
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.
Here's how you might define the User class with a public property:
class User {
constructor(id) {
[Link] = id; // Public property
}
}
[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;
}
// 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
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!
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.