FDT JS-101 (Java Script) Sprint Summary

Modified on Wed, 3 Jul at 11:50 PM

Usage Directions:


This is Java Script tech stack summary Part-1, discussed in the JS-101 Sprint. Revising the entire content is estimated to require one-two hours of effort, assuming you have prior exposure to the same tech stack. We recommend approaching this task in parts for a more effective revision process.


All the best!




TABLE OF CONTENTS





Topic 1: JS Intro

Need of JavaScript

JavaScript is a high-level programming language that is primarily used for adding interactivity and dynamic behavior to websites.

JavaScript is used in various contexts, including web development, mobile app development, server-side programming, game development, and more. It is predominantly utilized on the client-side (in web browsers) to enhance user experience and provide interactive features.



Topic 2: Data Types

Primitive Data Types in JS

In JavaScript, primitive data types are the basic building blocks for storing and manipulating data, including numbers, strings, booleans, null, and undefined.

Here are the common primitive data types in JavaScript and how they are used:
1. Number: Represents numeric values and supports mathematical operations.
2. String: Represents textual data and is enclosed in single quotes ('') or double quotes ("").
3. Boolean: Represents a logical value, either true or false.
4. Null: Represents the intentional absence of any object value.
5. Undefined: Represents an uninitialized variable or an object property that does not exist.

Code snippet:

// Example of using primitive data types
let age = 25; // Number
let name = "John"; // String
let isStudent = true; // Boolean
let score = null; // Null
let address; // Undefined

console.log(typeof age); // Output: number
console.log(typeof name); // Output: string
console.log(typeof isStudent); // Output: boolean
console.log(typeof score); // Output: object (a known quirk in JavaScript)
console.log(typeof address); // Output: undefined


Takeaways / best practices:
- Use the appropriate primitive data type based on the nature of the data you need to store.
- Be aware of JavaScript's dynamic typing, which allows variables to change their data type during runtime.
- Use strict equality (===) to compare values and avoid unexpected type coercion.
- Be cautious with the typeof operator, as it may produce unexpected results for some data types (e.g., typeof null returns "object").
- Use null to represent the absence of an object value, and undefined for uninitialized variables or missing object properties.
- Pay attention to data type conversions and understand how JavaScript handles implicit and explicit type conversions.



Topic 3: Variables

Variable declaration and initialization in JS

Variable declaration in JavaScript refers to the process of creating a named container to store data. It involves specifying a name for the variable and optionally assigning an initial value.

They can be used within functions, loops, conditionals, or at the global scope.

Here are the steps involved in variable declaration and usage in JavaScript:
1. Declaration: To declare a variable, use the `var`, `let`, or `const` keyword followed by the variable name.
- `var`: Declares a variable with function scope or global scope.
- `let`: Declares a block-scoped variable that can be reassigned.
- `const`: Declares a block-scoped variable that is read-only (immutable).
2. Initialization: Optionally, you can assign an initial value to the variable using the assignment operator (=).
- The initial value can be a literal value (e.g., a number, string, boolean) or the result of an expression.
3. Usage: Once declared and initialized, you can use the variable to store, retrieve, and manipulate data throughout your code.

Code snippet:

// Variable declaration and initialization
let age; // Declaration without initialization
age = 25; // Initialization

// Variable declaration and initialization in one line
let name = "John";
const PI = 3.14;

// Variable usage
console.log("My age is " + age); // Output: My age is 25
console.log("My name is " + name); // Output: My name is John
console.log("The value of PI is " + PI); // Output: The value of PI is 3.14


Takeaways / best practices:
- Use `let` or `const` instead of `var` for the variable declaration to leverage block scope and avoid common pitfalls associated with function scope.
- Prefer `const` for variables that should not be reassigned, as it promotes immutability and helps prevent accidental modifications.
- Declare variables at the smallest scope necessary to improve code readability and maintainability.
- Choose meaningful variable names that accurately represent the data they store.
- Initialize variables at the point of declaration whenever possible to clearly indicate their intended initial values.
- Be aware of variable hoisting in JavaScript, which allows variables to be accessed before they are declared. However, it is recommended to declare variables before using them for better code organization.


Variable reassignment

Variable reassignment in JavaScript refers to the act of assigning a new value to an existing variable.

After the initial assignment, the value of a variable can be changed by assigning a new value to it.
- The variable must already be declared in the current scope before reassigning a value to it.
- The new value can be a literal value or the result of an expression or function call.

Variables declared with `var` or `let` are mutable, meaning their values can be changed after the assignment.

Variables declared with `const` are immutable and cannot be reassigned once they have been assigned a value.

Code snippet:

let count = 5; // Initial assignment
count = count + 1; // Reassignment using an expression
console.log(count); // Output: 6

count = 10; // Reassignment with a new value
console.log(count); // Output: 10

const PI = 3.14; // Initial assignment with const

// Attempting to reassign a new value to a const variable will result in an error
// PI = 3.14159; // SyntaxError: Assignment to constant variable.


Takeaways / best practices:
- Variable reassignment can be used to update the value of a variable as needed throughout the execution of a JavaScript program.
- Be cautious with variable reassignment, as it can make code harder to understand and debug.
- Use descriptive variable names to make it clear what the variable represents, even after reassignment.
- When using `let` or `var`, consider initializing variables with an initial value at the point of declaration to avoid confusion or unintended behavior.
- Use `const` for variables that should not be reassigned, as it promotes immutability and helps prevent accidental modifications.
- Understand the scope of variables and ensure they are declared within the appropriate scope before reassigning their values.


Topic 4: Expressions

Expressions

In JavaScript, an expression is a combination of values, variables, operators, and function calls that evaluates to a resulting value.

Expressions are used throughout JavaScript in various contexts, such as assignments, conditionals, loops, function arguments, and more.

When an expression is encountered in JavaScript, it is evaluated to produce a resulting value.
- The evaluation process involves following the operator precedence and associativity rules defined in JavaScript.
The resulting value of an expression can be assigned to a variable, used as a condition in a control structure (e.g., if statement), passed as an argument to a function, or used in any other context where a value is expected.

Code snippet:

let a = 5;
let b = 10;
let sum = a + b; // Expression: a + b
console.log(sum); // Output: 15

let isGreater = a > b; // Expression: a > b
console.log(isGreater); // Output: false

let fullName = "John" + " " + "Doe"; // Expression: "John" + " " + "Doe"
console.log(fullName); // Output: "John Doe"

Takeaways / best practices:
- Expressions are fundamental in JavaScript and are used extensively in programming to perform calculations, comparisons, and generate dynamic values.
- Understand operator precedence and associativity to ensure correct evaluation of expressions.
- Use parentheses to explicitly specify the order of evaluation and to make code more readable.
- Break complex expressions into smaller, more manageable parts to improve code readability and maintainability.
- Avoid overly complex or convoluted expressions that can make code harder to understand and debug.



Topic 5: Operators

Arithmetic Operators and their Precedence

Arithmetic operators in JavaScript are symbols used to perform mathematical operations on operands and produce a resulting value.

How is it used?
Here are the common arithmetic operators in JavaScript and their precedence rules:
1. Addition (+): Adds two operands or concatenates strings.
2. Subtraction (-): Subtracts the right operand from the left operand.
3. Multiplication (*): Multiplies two operands.
4. Division (/): Divides the left operand by the right operand.
5. Remainder (%): Returns the remainder of the division of the left operand by the right operand.
6. Exponentiation (**): Raises the left operand to the power of the right operand.
7. Increment (++) and Decrement (--): Increases or decreases the value of an operand by 1.
8. Unary plus (+) and Unary minus (-): Converts the operand into a number and changes its sign, respectively.

Here is the priority order, from highest to lowest:
Grouping with parentheses ()
Exponentiation ** (highest priority)
Multiplication *, Division /, and Remainder % (same priority, evaluated left to right)
Addition + and Subtraction - (same priority, evaluated left to right)
Operators with higher priority are evaluated first. Within the same priority level, operators are evaluated from left to right. Parentheses can be used to explicitly specify the order of evaluation and override the default priority.

Precedence rules:
- Operators with higher precedence are evaluated first.
- Parentheses can be used to override the default precedence and explicitly specify the order of evaluation.

Code snippet:

let a = 5;
let b = 3;
let sum = a + b; // Addition
console.log(sum); // Output: 8

let difference = a - b; // Subtraction
console.log(difference); // Output: 2

let product = a * b; // Multiplication
console.log(product); // Output: 15

let quotient = a / b; // Division
console.log(quotient); // Output: 1.6666666666666667

let remainder = a % b; // Remainder
console.log(remainder); // Output: 2

let exponentiation = a ** b; // Exponentiation
console.log(exponentiation); // Output: 125

let increment = a++; // Increment
console.log(increment); // Output: 5 (post-increment)

let decrement = --b; // Decrement
console.log(decrement); // Output: 2 (pre-decrement)

let positive = +a; // Unary plus
console.log(positive); // Output: 6

let negative = -b; // Unary minus
console.log(negative); // Output: -2


Takeaways / best practices:

- Understand the precedence of arithmetic operators to ensure the correct evaluation of expressions.
- Use parentheses to explicitly specify the order of evaluation when needed and to improve code readability.
- Be aware of potential precision issues with division (/) and use appropriate techniques (e.g., rounding, limiting decimal places) when necessary.
- Use the increment (++) and decrement (--) operators with caution, as their behavior can differ depending on their position (pre-increment vs. post-increment).
- Practice code readability by using whitespace and proper formatting to enhance the clarity of expressions involving arithmetic operators.
- Familiarize yourself with operator precedence to construct complex expressions correctly and avoid unexpected results.


Relational Operators

Relational operators in JavaScript are used to compare two values and return a boolean value indicating the relationship between them (e.g., greater than, less than, equal to).

Relational operators are commonly used in JavaScript for comparisons, conditional statements, and decision-making processes.

Here are the relational operators in JavaScript and how they are used:
1. Greater than (>): Checks if the value on the left is greater than the value on the right.
2. Greater than or equal to (>=): Checks if the value on the left is greater than or equal to the value on the right.
3. Less than (<): Checks if the value on the left is less than the value on the right.
4. Less than or equal to (<=): Checks if the value on the left is less than or equal to the value on the right.
5. Equality (==): Checks if the values on the left and right are equal.
6. Inequality (!=): Checks if the values on the left and right are not equal.
7. Strict equality (===): Checks if the values on the left and right are equal and of the same type.
8. Strict inequality (!==): Checks if the values on the left and right are not equal or not of the same type.

Code snippet:

let a = 5;
let b = 10;
console.log(a > b); // Output: false
console.log(a >= b); // Output: false
console.log(a < b); // Output: true
console.log(a <= b); // Output: true
console.log(a == b); // Output: false
console.log(a != b); // Output: true
console.log(a === b); // Output: false
console.log(a !== b); // Output: true


Takeaways / best practices:
- Use strict equality (`===`) and strict inequality (`!==`) by default, as they help avoid unexpected type coercion.
- Understand how JavaScript compares different types of values (e.g., numbers, strings, objects) using relational operators.
- When comparing strings, JavaScript uses lexicographical (dictionary) order, which compares the ASCII or Unicode values of characters.
- Combine relational operators with logical operators (`&&`, `||`, `!`) to create complex comparisons and conditions.
- Use parentheses to clarify the order of operations and improve code readability when combining multiple relational operators.


Logical Operators

Logical operators in JavaScript are used to combine and manipulate boolean values to create more complex logical expressions.

Logical operators are commonly used in JavaScript for conditional statements, boolean expressions, and logical decision-making.

Here are the logical operators in JavaScript and how they are used:
1. Logical AND (&&): Returns true if both operands are true, otherwise returns false.
2. Logical OR (||): Returns true if at least one of the operands is true, otherwise returns false.
3. Logical NOT (!): Reverses the boolean value of the operand.

Code snippet:

let a = true;
let b = false;

console.log(a && b); // Output: false
console.log(a || b); // Output: true
console.log(!a); // Output: false
console.log(!b); // Output: true


Takeaways / best practices:
- Understand short-circuit evaluation: JavaScript evaluates logical expressions from left to right and stops evaluation as soon as the result can be determined. This behavior allows for efficient evaluation and can be used for conditional assignments or checks.
- Be mindful of operator precedence and use parentheses to explicitly specify the order of evaluation when combining logical operators with other operators.
- Use meaningful variable and function names to make logical expressions more readable and understandable.
- Avoid unnecessary complexity in logical expressions. Break complex conditions into smaller, more manageable parts to improve code readability and maintainability.
- Use comments to explain the purpose and logic of complex logical expressions, especially if they involve multiple operators and conditions.


Topic 6: Conditionals

if-else statement

The if-else statement in JavaScript is a control flow statement that allows you to execute different blocks of code based on a specified condition.

Here are the steps to use the if-else statement in JavaScript:
1. The if statement: It starts with the keyword `if`, followed by a condition enclosed in parentheses. The condition is evaluated to either true or false.
2. If the condition is true, the block of code inside the if statement is executed.
3. If the condition is false, the code inside the if block is skipped, and the program moves to the next part.
4. The else statement: It is optional and used to specify an alternative block of code to be executed when the condition in the if statement is false.
5. The else block is preceded by the keyword `else` and followed by a block of code that will be executed if the condition is false.

Code snippet:

let num = 10;
if (num > 0) {
  console.log("The number is positive");
} else {
  console.log("The number is non-positive");
}

//  Output:  The number is positive      


Takeaways / best practices:
- Use logical operators (`&&`, `||`, `!`) to create complex conditions in the if statement.
- Avoid nested if-else statements that are too deeply nested, as they can reduce code readability and make it harder to understand and maintain.
- Consider using switch statements for more complex conditional logic, especially when you have multiple conditions and possible outcomes.
- Comment your code to explain the purpose and logic of the if-else statement, especially when the condition or the code inside the blocks may not be self-explanatory.


Topic 7: Functions

Defining a function

Defining a function in JavaScript involves creating a named block of code that can be invoked and executed later.

Functions are used in JavaScript to organize and modularize code, promote reusability, and encapsulate logic for specific tasks or operations.

Here are the steps to define a function in JavaScript:
1. Function declaration: Start with the `function` keyword, followed by the name of the function.
2. Parameters: Declare any parameters that the function may accept within parentheses. Parameters act as placeholders for values that will be passed into the function when it is invoked.
3. Function body: Enclose the code that makes up the function's logic within curly braces `{}`.
4. Statements: Write the statements or code that define the functionality of the function within the function body.
5. Return statement: Optionally, include a `return` statement within the function body to specify the value that the function will return when it is invoked.
6. Function invocation: To execute the function and make use of its logic, call or invoke the function by its name, followed by parentheses. Provide any necessary arguments or values for the function's parameters.

Code snippet:

function greet(name) {
    return "Hello, " + name + "!";
}
let result = greet("John");
console.log(result);        

// Output: Hello, John!


Takeaways / best practices:
- Use descriptive names for functions that reflect their purpose or what they accomplish.
- Functions can be invoked multiple times with different arguments, allowing for flexibility and reusability.
- Follow a consistent coding style and use proper indentation and formatting to enhance code readability.
- Use comments to document the purpose, input, output, and any other relevant information about the function.
- Break down complex tasks into smaller, well-organized functions to improve code maintainability and readability.


Parameters vs Arguments

In JavaScript, parameters and arguments are used in the context of functions to handle inputs and pass values between the function definition and function invocation. Parameters and arguments are used when defining and invoking functions in JavaScript.

Parameters:
- Parameters are placeholders defined in the function declaration.
- They represent the inputs that a function expects to receive when it is invoked.
- Parameters are listed inside the parentheses of the function declaration and separated by commas.
- Parameters are variables local to the function.

Arguments:
- Arguments are the actual values passed to a function when it is invoked.
- Arguments correspond to the parameters defined in the function declaration.
- When a function is invoked, the arguments are provided inside the parentheses of the function invocation and separated by commas.
- The number and order of arguments passed must match the number and order of parameters declared in the function.
- Arguments can be any valid JavaScript expression, including literals, variables, or expressions.
- Arguments supply the values that the function will work with during its execution.

Code snippet:

function greet(name) {      // name is the parameter
  console.log("Hello, " + name + "!");
}
let personName = "John";
greet(personName);  // personName is the argument


Takeaways / best practices:
- Choose descriptive names for both parameters and arguments to enhance code readability.
- Use default parameter values to provide fallback values when arguments are not passed.
- Be mindful of the data types expected by the parameters and ensure that the corresponding arguments are of compatible types.
- Document the expected parameters and their purpose in function comments or documentation to provide clarity to other developers using your code.


Topic 8: Conditionals 2

if else chain

The if-else chain in JavaScript is a series of if-else statements that are chained together to perform conditional execution based on multiple conditions.

The if-else chain is used in JavaScript to handle complex decision-making scenarios where multiple conditions need to be evaluated sequentially.

How is it used?
Here are the steps to use an if-else chain in JavaScript:
1. Start with an initial if statement that contains a condition to be evaluated.
2. If the condition in the initial if statement is true, the corresponding block of code inside the if block is executed, and the rest of the if-else chain is skipped.
3. If the condition in the initial if statement is false, move to the next else-if statement in the chain.
4. Each else-if statement contains a condition to be evaluated.
5. If the condition in an else-if statement is true, the corresponding block of code inside the else-if block is executed, and the rest of the if-else chain is skipped.
6. If none of the conditions in the if and else-if statements are true, the code inside the final else block is executed as a fallback.

Code snippet:

let age = 25;
if (age < 18) {
  console.log("You are a minor");
} else if (age >= 18 && age <= 65) {
  console.log("You are an adult");
} else {
  console.log("You are a senior citizen");
}

//  Output  :  You are an adult


Takeaways / best practices:
- Order the if and else-if statements from most specific to most general conditions to ensure proper evaluation.
- Use meaningful variable and function names to make the conditions in the if-else chain more readable and self-explanatory.
- Comment your code to explain the purpose and logic of each condition in the if-else chain, especially when the conditions are not straightforward or when there are multiple conditions to consider.
- Test your if-else chain with different input values to ensure that all possible scenarios are handled correctly.


Nested if-else

Nested if-else statements in JavaScript are conditional statements that are nested inside other if or else blocks, allowing for multiple levels of conditional execution.

Nested if-else statements are used in JavaScript to handle complex decision-making scenarios where conditions need to be evaluated at multiple levels or nested conditions depending on the outcome of outer conditions.

Code snippet:

let num = 15;
if (num > 0) {
  console.log("Number is positive");
  if (num % 2 === 0) {
    console.log("Number is even");
  } else {
    console.log("Number is odd");
  }
} else {
  console.log("Number is non-positive");
}

/*Output:

Number is positive

Number is odd       */


Takeaways / best practices:
- Maintain proper indentation and formatting to make nested if-else statements more readable.
- Avoid excessive nesting of if-else statements to prevent code from becoming too complex and difficult to understand.
- Consider refactoring complex nested if-else statements into separate functions or using other control flow structures, such as switch statements, to improve code readability and maintainability.
- Comment your code to explain the purpose and logic of each condition in the nested if-else statements, especially when the conditions or the code inside the blocks are not self-explanatory.
- Test your nested if-else statements with different input values to ensure that all possible scenarios are handled correctly.



Topic 9: Strict Mode

Strict Mode

Strict mode is a feature in JavaScript that enforces stricter rules and better error handling, helping to prevent common coding mistakes and improve code quality.

How is it used?
Here are the steps to enable strict mode in JavaScript:
1. Enable strict mode globally: Add the `'use strict';` directive at the beginning of a JavaScript file or script tag to enable strict mode for the entire file or script.
2. Enable strict mode within a function: Add the `'use strict';` directive at the beginning of a function to enable strict mode only within that specific function.

Code snippet:

'use strict';
// Strict mode enabled globally

function calculate() {
  'use strict';
  // Strict mode enabled within this function
}


Takeaways / best practices:
- Enabling strict mode is considered a best practice, and it is recommended to use it in all JavaScript code to improve code quality, maintainability, and catch potential errors early in the development process.
- Strict mode is backward compatible, meaning it can be safely added to existing code without breaking any existing functionality, as long as the code does not rely on any deprecated or error-prone features.


Topic 10: Strings


Strings

In JavaScript, a string is a sequence of characters used to represent text. It is a primitive data type that is enclosed in single quotes ('') or double quotes ("").

Strings are used in JavaScript for a wide range of purposes, such as displaying messages, storing user input, manipulating text, and interacting with APIs and databases.


Accessing characters in string

Accessing characters in a string is commonly used when you need to manipulate or extract specific characters from text-based data, such as parsing user input, validating strings, or performing string transformations.

1. Bracket notation: Use bracket notation (`[]`) with the index position to access a specific character within the string. The index starts from 0 for the first character.
2. charAt() method: Alternatively, use the `charAt()` method by passing the index as an argument to retrieve the character at that position.
3. Length property: Use the `length` property of a string to determine the total number of characters in the string.
4. Looping over characters: Iterate over each character in a string using a loop, such as a for loop or a for...of loop, to perform operations on each character.

Code snippet:


let message = "Hello, World!";

let firstCharacter = message[0]; // Access the first character using bracket notation
console.log(firstCharacter); // Output: H

let secondCharacter = message.charAt(1); // Access the second character using charAt()
console.log(secondCharacter); // Output: e

let lastCharacter = message[message.length - 1]; // Access the last character using bracket notation and length property
console.log(lastCharacter); // Output: !

// Looping over characters
for (let i = 0; i < message.length; i++) {
  console.log(message[i]);
}
/* Output:
H
e
l
l
o
,

W
o
r
l
d
!
*/


Takeaways / best practices:
- Be cautious when accessing characters using bracket notation or `charAt()` with an index that is out of range, as it will return undefined.
- To access the last character of a string using bracket notation, subtract 1 from the length of the string (`string.length - 1`).
- Be mindful of Unicode characters and surrogate pairs, as they can occupy more than one index position in a string.
- String characters are immutable, meaning you cannot directly change a character at a specific index. Instead, you need to create a new string with the desired modifications.
- Regularly test your code when working with strings to ensure the expected characters are accessed and processed correctly.


String immutability

String immutability in JavaScript means that once a string is created, its value cannot be changed. Any operation that appears to modify a string actually creates a new string with the desired modifications.

String methods, such as `toUpperCase()`, `substring()`, or `replace()`, do not modify the original string. Instead, they return a new string with the applied modifications.

When concatenating strings using the `+` operator or the `concat()` method, a new string is created with the combined contents of the original strings.
To modify a string, you need to assign the new string to a different variable or the same variable, overwriting the original value.

Code snippet:

let originalString = "Hello, World!";
let upperCaseString = originalString.toUpperCase(); // Returns a new string with all characters converted to uppercase
console.log(upperCaseString); // Output: HELLO, WORLD!
console.log(originalString); // Output: Hello, World! (Original string is unchanged)

let concatenatedString = originalString + " Welcome!"; // Concatenates the original string with additional text
console.log(concatenatedString); // Output: Hello, World! Welcome!
console.log(originalString); // Output: Hello, World! (Original string is unchanged)

originalString = originalString.replace("World", "Universe"); // Assigns the new modified string to the same variable
console.log(originalString); // Output: Hello, Universe! (Original string is overwritten)


Template Strings

Template Strings, also known as template literals, are a way to create strings in JavaScript that allow for easy embedding of variables or expressions within the string.

Template Strings are commonly used when you need to concatenate strings with dynamic values, such as generating dynamic messages, constructing URLs, or building HTML templates.

How is it used?
Here are the steps to use Template Strings in JavaScript:
1. Syntax: Template Strings are enclosed within backticks (`) instead of single or double quotes.
2. Variable interpolation: To embed a variable or expression within a Template String, enclose it in `${}`.
3. String concatenation: You can include static text alongside variables and expressions by directly typing it within the Template String.
4. Multiline strings: Template Strings also allow for multiline strings without the need for explicit line breaks.
5. Escape characters: Backticks and dollar signs within a Template String can be escaped using a backslash (\) if needed.

Code snippet:

let name = "Alice";
let age = 25;

// Basic usage: Embedding variables
let message = `Hello, ${name}! You are ${age} years old.`;
console.log(message); // Output: Hello, Alice! You are 25 years old.

// Expressions within Template Strings
let sum = `The sum of 2 and 3 is ${2 + 3}.`;
console.log(sum); // Output: The sum of 2 and 3 is 5.

// Multiline strings
let multiline = `
  This is a
  multiline
  string.
`;
console.log(multiline);
/* Output:
  This is a
  multiline
  string.
*/
// Escape characters
let escaped = `This is a backtick: \`. And this is a dollar sign: \${}.`;
console.log(escaped);     // Output: This is a backtick: `. And this is a dollar sign: ${}.


Takeaways / best practices:
- Avoid using Template Strings for simple string literals that do not require variable interpolation.
- When using Template Strings with expressions, ensure the expressions are evaluated correctly and consider wrapping complex expressions in parentheses for clarity.
- Take advantage of the multiline feature of Template Strings for readability, especially when dealing with long strings or multiline outputs.



Topic 11: String Methods

indexOf() and lastIndexOf()

The `indexOf()` and `lastIndexOf()` methods are string methods in JavaScript used to search for the first and last occurrence of a substring within a string, respectively.

These methods are commonly used when you need to find the position of a substring within a string or check if a substring exists within a larger string.

How is it used?
Here are the steps to use `indexOf()` and `lastIndexOf()` in JavaScript:
1. Syntax: Both methods are called on a string and accept a substring as an argument.
2. `indexOf()`: Returns the index of the first occurrence of the substring within the string. If the substring is not found, it returns -1.
3. `lastIndexOf()`: Returns the index of the last occurrence of the substring within the string. If the substring is not found, it returns -1.
4. Optional second parameter: Both methods can also accept an optional second parameter specifying the starting index from where the search should begin.
5. Case-sensitive: By default, both methods are case-sensitive. To perform a case-insensitive search, you can convert both the string and the substring to lowercase or uppercase before using these methods.

Code snippet:

let str = "Hello, world! Welcome to JavaScript!";
console.log(str.indexOf("o")); // Output: 4 (Index of the first 'o' in the string)
console.log(str.lastIndexOf("o")); // Output: 23 (Index of the last 'o' in the string)
console.log(str.indexOf("JavaScript")); // Output: 25 (Index of the first occurrence of "JavaScript")
console.log(str.lastIndexOf("JavaScript")); // Output: 25 (Index of the last occurrence of "JavaScript")
console.log(str.indexOf("o", 5)); // Output: 8 (Index of the first 'o' starting from index 5)
console.log(str.lastIndexOf("o", 10)); // Output: 8 (Index of the last 'o' searching up to index 10)
console.log(str.indexOf("abc")); // Output: -1 (Substring "abc" not found)
console.log(str.lastIndexOf("abc")); // Output: -1 (Substring "abc" not found)
console.log(str.indexOf("world")); // Output: 7 (Case-sensitive search)
console.log(str.toLowerCase().indexOf("world")); // Output: 7 (Case-insensitive search)


substring()

The `substring()` method is a string method in JavaScript used to extract a portion of a string and return it as a new string.

How is it used?
Here are the steps to use `substring()` in JavaScript:
1. Syntax: The `substring()` method is called on a string and accepts two parameters: the starting index and the optional ending index.
2. Starting index: Specify the index at which the desired substring should start. This index is inclusive, meaning the character at that index will be included in the substring.
3. Ending index: Optionally, specify the index at which the desired substring should end. This index is exclusive, meaning the character at that index will not be included in the substring. If the ending index is not provided, the substring will include all characters from the starting index to the end of the string.
4. Return value: The `substring()` method returns a new string that contains the extracted portion of the original string.

Code snippet:

let str = "Hello, world!";

let substring1 = str.substring(7); // Extracts from index 7 to the end
console.log(substring1); // Output: "world!"

let substring2 = str.substring(0, 5); // Extracts from index 0 to index 5 (exclusive)
console.log(substring2); // Output: "Hello"

let substring3 = str.substring(7, 12); // Extracts from index 7 to index 12 (exclusive)
console.log(substring3); // Output: "world"

let substring4 = str.substring(7, 20); // Ending index greater than string length, treated as string length
console.log(substring4); // Output: "world!"

let substring5 = str.substring(12, 7); // Swapping the indices, same as substring(7, 12)
console.log(substring5); // Output: "world"

let substring6 = str.substring(7, 7); // Starting and ending index are the same, empty string
console.log(substring6); // Output: ""


concat()

The `concat()` method is a string method in JavaScript used to concatenate two or more strings and return a new string.

1. Syntax: The `concat()` method is called on a string and accepts one or more string arguments.
2. Arguments: Pass the strings that you want to concatenate as arguments to the `concat()` method. You can provide multiple arguments separated by commas, and they will be concatenated in the order they appear.
3. Return value: The `concat()` method returns a new string that contains the concatenated result of all the provided strings.

Code snippet:

let str1 = "Hello";
let str2 = "World";
let str3 = "!";
let result = str1.concat(str2, str3);
console.log(result); // Output: "HelloWorld!"

let firstName = "John";
let lastName = "Doe";
let fullName = firstName.concat(" ", lastName);
console.log(fullName); // Output: "John Doe"


Topic 12: for loop

for loop

The for loop is a control flow statement used to repeatedly execute a block of code based on a specified condition. It allows iterating over a sequence of values or elements.

The for loop is commonly used in JavaScript and other programming languages when you want to perform a repetitive task a certain number of times or iterate over an array or object.

Here are the steps to use a for loop in JavaScript:
1. Initialize a counter variable (usually named `i`) to the starting value.
2. Define the condition that specifies when the loop should continue executing.
3. Perform the code block inside the loop.
4. Update the counter variable at the end of each iteration.
5. Repeat steps 2-4 until the condition becomes false.

Example code snippet:

for (let i = 0; i < 5; i++) {
  console.log("Iteration: " + i);
}

/* Output:
Iteration: 0
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4  */


Takeaways / Best practices:
- Use meaningful variable names to enhance code readability.
- Consider using `const` instead of `let` if the loop variable doesn't need to be reassigned within the loop.



Topic 13: Array in JS

Array in JS

An array in JavaScript is a data structure that allows storing multiple values in a single variable. It is an ordered collection of elements where each element can be accessed using an index.

Arrays are widely used in JavaScript for storing and manipulating collections of data. They are commonly used to hold lists of items, iterate over elements, and perform various operations like adding, removing, or modifying elements.

1. Declare an array variable using the square brackets `[]`.
2. Assign values to the array using comma-separated elements enclosed in the brackets.

Example code snippet:

// Declaring an array
let fruits = ['apple', 'banana', 'orange'];
console.log(fruits);  // Output:  ['apple', 'banana', 'orange']


Takeaways/Best practices:
- The length of an array can be accessed using the `length` property (`arrayName.length`).
- Use descriptive variable names and consider using `const` instead of `let` when the array reference won't change.


Accessing and modifying elements in the array

Accessing and modifying array elements is a fundamental operation used in JavaScript when working with arrays to retrieve, update, or manipulate specific data points within the array.

- How is it used?
Here are the steps to access and modify elements in an array in JavaScript:
1. Accessing Elements:
- Use square brackets `[]` and provide the index of the element you want to access within the array.
- The index starts at 0 for the first element, 1 for the second, and so on.
- Access the element using the array variable name followed by the index, such as `arrayName[index]`.
2. Modifying Elements:
- Use the same square bracket notation to access the element you want to modify.
- Assign a new value to the element using the assignment operator (`=`).

Example code snippet:

// Accessing elements in an array
let fruits = ['apple', 'banana', 'orange'];
console.log(fruits[0]);  // Output: 'apple'

// Modifying elements in an array
fruits[1] = 'grape';
console.log(fruits);  // Output: ['apple', 'grape', 'orange']


Takeaways / Best practices:
- Ensure the index you provide is within the valid range of the array (0 to length-1) to avoid errors.
- Arrays in JavaScript are mutable, meaning you can modify their elements directly.



Topic 14: Array Methods

push() array method

The push() method is an array method in JavaScript used to add one or more elements to the end of an array and returns the new length of the array.

Example code snippet:

// Using push() to add elements to an array
let fruits = ['apple', 'banana', 'orange'];
console.log(fruits);  // Output: ['apple', 'banana', 'orange']

fruits.push('grape');
console.log(fruits);  // Output: ['apple', 'banana', 'orange', 'grape']
fruits.push('kiwi', 'mango');
console.log(fruits);  // Output: ['apple', 'banana', 'orange', 'grape', 'kiwi', 'mango']


Takeaways / Best practices:
- The push() method adds element(s) to the end of an array, modifying the original array.
- Multiple elements can be added by passing them as separate arguments to the push() method.
- The push() method returns the new length of the array after the addition, which can be useful in certain scenarios.
- Be mindful of the order in which elements are added with push(), as they will appear in the array accordingly.


pop() array method

The pop() method is an array method in JavaScript used to remove the last element from an array and return that element.

Example code snippet:

// Using pop() to remove the last element from an array
let fruits = ['apple', 'banana', 'orange', 'grape'];
console.log(fruits);  // Output: ['apple', 'banana', 'orange', 'grape']

let removedElement = fruits.pop();
console.log(removedElement);  // Output: 'grape'
console.log(fruits);          // Output: ['apple', 'banana', 'orange']


Takeaways / Best practices:
- The pop() method removes the last element from an array, modifying the original array.
- The removed element is returned by the pop() method and can be stored in a variable for further use.
- Calling pop() on an empty array returns undefined.
- Consider checking the length of the array before calling pop() to avoid errors when the array is empty.


shift() array method

The shift() method is an array method in JavaScript used to remove the first element from an array and return that element.

Example code snippet:

// Using shift() to remove the first element from an array
let fruits = ['apple', 'banana', 'orange', 'grape'];
console.log(fruits);  // Output: ['apple', 'banana', 'orange', 'grape']

let removedElement = fruits.shift();
console.log(removedElement);  // Output: 'apple'
console.log(fruits);          // Output: ['banana', 'orange', 'grape']


Takeaways / Best practices:
- The shift() method removes the first element from an array, modifying the original array.
- Calling shift() on an empty array returns undefined.
- Consider checking the length of the array before calling shift() to avoid errors when the array is empty.


unshift() array method

The unshift() method is an array method in JavaScript used to add one or more elements to the beginning of an array and returns the new length of the array

Example code snippet:

// Using unshift() to add elements to the beginning of an array
let fruits = ['banana', 'orange', 'grape'];
console.log(fruits);  // Output: ['banana', 'orange', 'grape']

let newLength = fruits.unshift('apple');
console.log(newLength);  // Output: 4
console.log(fruits);     // Output: ['apple', 'banana', 'orange', 'grape']
fruits.unshift('kiwi', 'mango');
console.log(fruits);     // Output: ['kiwi', 'mango', 'apple', 'banana', 'orange', 'grape']


Takeaways / Best practices:
- The unshift() method adds element(s) to the beginning of an array, modifying the original array.
- Multiple elements can be added by passing them as separate arguments to the unshift() method.
- The unshift() method returns the new length of the array after the addition, which can be useful in certain scenarios.
- Be mindful of the order in which elements are added with unshift(), as they will appear in the array accordingly.


reverse() array method

The reverse() method is an array method in JavaScript used to reverse the order of elements in an array.

Example code snippet:

// Using reverse() to reverse the order of elements in an array
let fruits = ['apple', 'banana', 'orange', 'grape'];
console.log(fruits);  // Output: ['apple', 'banana', 'orange', 'grape']

fruits.reverse();
console.log(fruits);  // Output: ['grape', 'orange', 'banana', 'apple']

Takeaways / Best practices:
- There is no need to assign the result of reverse() to a new variable as it directly modifies the original array.
- Consider creating a copy of the array if you need to preserve the original order while also having a reversed version.


Topic 15: Equality Comparators

Equality Comparators

Equality comparators in JavaScript are operators used to compare values for equality or inequality.

Equality comparators are used in various scenarios where you need to compare values, such as conditional statements, sorting, filtering, and searching data.

1. Equal to (==):
- The == operator checks if two values are equal, performing type coercion if necessary.
- If the types of the two values are different, JavaScript attempts to convert them to a common type before comparison.
- Example: `2 == "2"` returns true.
2. Not equal to (!=):
- The != operator checks if two values are not equal, performing type coercion if necessary.
- Example: `3 != "3"` returns false.
3. Strict equal to (===):
- The === operator checks if two values are equal, without performing type coercion.
- It compares both the values and their types.
- Example: `5 === 5` returns true, but `5 === "5"` returns false.
4. Strict not equal to (!==):
- The !== operator checks if two values are not equal, without performing type coercion.
- It compares both the values and their types.
- Example: `7 !== "7"` returns true.

Example code snippet:

let num1 = 10;
let num2 = "10";
console.log(num1 == num2);    // Output: true
console.log(num1 === num2);   // Output: false
console.log(num1 != num2);    // Output: false
console.log(num1 !== num2);   // Output: true


Topic 16: Truthy and Falsy values

Truthy and Falsy values

In JavaScript, truthy and falsy values refer to values that are evaluated as either true or false in a boolean context.

Truthy and falsy values are used in conditional statements, logical operations, and type coercion in JavaScript.

- How is it used?
Here are the key points to understand about truthy and falsy values in JavaScript:
1. Truthy values:
- Truthy values are values that are considered true when evaluated in a boolean context.
- Examples of truthy values include non-empty strings, numbers other than 0, arrays, objects, and non-null values.
- When a truthy value is used in an if statement or as a condition, the associated block of code will be executed.
- Example: `if ("hello") { console.log("Truthy"); }` will output "Truthy".

2. Falsy values:
- Falsy values are values that are considered false when evaluated in a boolean context.
- Examples of falsy values include an empty string (`""`), the number 0, NaN (Not a Number), null, undefined, and false.
- When a falsy value is used in an if statement or as a condition, the associated block of code will not be executed.
- Example: `if (0) { console.log("Falsy"); }` will not output anything.

Example code snippet:

// Checking truthy and falsy values

let name = "";
let age = 25;
if (name) {
  console.log("Truthy");
} else {
  console.log("Falsy");
}

if (age) {
  console.log("Truthy");
} else {
  console.log("Falsy");
}

/* Output:
Falsy
Truthy   */


Takeaways / Best practices:
- Understand the concept of truthy and falsy values to write effective conditional statements and perform type coercion.
- Be aware of the specific values that are considered truthy or falsy in JavaScript.
- Use truthy and falsy values to your advantage to write concise and readable code.
- When comparing values for equality, consider using strict equality (`===`) to avoid unexpected truthy/falsy results due to type coercion.
- Avoid relying on implicit type coercion when writing conditionals, as it can lead to confusing and error-prone code. Be explicit in your comparisons.
- Understanding truthy and falsy values is essential for writing logical and robust code in JavaScript. By knowing the values that are considered truthy or falsy, you can handle conditions and boolean operations effectively in your programs.


Topic 17: Searching in array

includes()

The includes() method is an array method in JavaScript used to check if an array includes a specific element and returns true or false accordingly.

Example code snippet:

// Using includes() to check if an array includes a specific element
let numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(3));    // Output: true
console.log(numbers.includes(6));    // Output: false
console.log(numbers.includes(1, 2)); // Output: false


Takeaways / Best practices:
- includes() performs strict equality (===) comparison to check for the presence of the element in the array.
- You can optionally specify a second argument in includes() to specify the index at which the search should start.
- includes() is case-sensitive when comparing strings.
- Be cautious when using includes() with arrays of objects, as it checks for object reference equality, not deep equality.


Topic 18: String to Array interconversions

split()

The split() method is a string method in JavaScript used to split a string into an array of substrings based on a specified separator.

Example code snippet:

// Using split() to split a string into an array
let sentence = "Hello, how are you today?";
let words = sentence.split(" ");
console.log(words);  // Output: ["Hello,", "how", "are", "you", "today?"]
let letters = sentence.split("");
console.log(letters);  // Output: ["H", "e", "l", "l", "o", ",", " ", "h", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", " ", "t", "o", "d", "a", "y", "?"]


Takeaways / Best practices:
- The separator can be a single character, a sequence of characters, or a regular expression.
- If no separator is provided, split() will split the string into individual characters.
- By default, split() does not modify the original string; it returns a new array.
- Use caution when dealing with empty strings or leading/trailing delimiters, as it may affect the resulting array.


join()

The join() method is an array method in JavaScript used to join all elements of an array into a single string, separated by a specified separator.

Example code snippet:

// Using join() to join elements of an array into a string
let fruits = ["apple", "banana", "orange"];
let joinedString = fruits.join(", ");
console.log(joinedString);  // Output: "apple, banana, orange"

let numbers = [1, 2, 3];
let joinedNumbers = numbers.join("-");
console.log(joinedNumbers);  // Output: "1-2-3"


Takeaways / Best practices:
- The separator can be a string or a character. If no separator is provided, a comma (",") will be used by default.
- The join() method does not modify the original array; it returns a new string.
- If the array contains elements that are `null` or `undefined`, they will be converted to empty strings in the resulting string.


Topic 19: 2D Array

2D array

A 2D array, also known as a two-dimensional array, is an array of arrays where each element can be accessed using two indices, representing rows and columns.

2D arrays are used when you need to represent tabular data, grids, matrices, or any other data structure that requires a two-dimensional arrangement of elements.

- How is it used?
Here are the steps to work with a 2D array in JavaScript:
1. Declare an array variable to hold the 2D array.
2. Initialize the array with arrays (sub-arrays) as elements, representing rows.
3. Access individual elements in the 2D array using two indices: the row index and the column index.
4. Perform operations on the elements based on the specific requirements of your program.

Example code snippet:

// Creating and accessing elements in a 2D array
let matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

console.log(matrix[0][0]); // Output: 1
console.log(matrix[1][2]); // Output: 6
console.log(matrix[2][1]); // Output: 8


Takeaways / Best practices:
- When creating a 2D array, each sub-array represents a row and can have different lengths.
- Be mindful of array bounds while accessing elements in a 2D array to avoid errors.
- Use nested loops for traversing and performing operations on all elements of a 2D array.


Topic 20: Objects in JS

Objects in JS

In JavaScript, an object is a data type that allows you to store multiple values as properties and methods, represented as key-value pairs.

Objects are widely used in JavaScript and are a fundamental part of the language. They are used to represent complex entities, such as a person, a car, or any real-world object that has properties and behaviors.

Example code snippet:

// Creating and using an object
let person = {
  name: "John",
  age: 30,
  occupation: "Engineer",
  greet: function() {
    console.log("Hello, my name is " + this.name);
  }
};

console.log(person.name);       // Output: "John"
console.log(person["age"]);     // Output: 30
person.greet();                 // Output: "Hello, my name is John"

person.age = 35;
console.log(person.age);        // Output: 35


Takeaways / Best practices:
- Properties in objects can hold any type of value, including numbers, strings, booleans, arrays, or even other objects.
- Methods in objects are functions associated with the object and can perform actions or calculations.
- The dot notation (`object.property`) is the preferred way to access properties and call methods in most cases.
- The square bracket notation (`object["property"]`) is useful when the property name is dynamic or contains special characters.
- Objects can be used to model and represent real-world entities or complex data structures.


hasOwnProperty()

hasOwnProperty() is a method in JavaScript that checks if an object has a specific property as its own property.

The method returns a boolean value (`true` or `false`) indicating whether the object has the specified property as its own property.

Example code snippet:

// Using hasOwnProperty()
let person = {
  name: "John",
  age: 30
};
console.log(person.hasOwnProperty("name"));       // Output: true
console.log(person.hasOwnProperty("age"));        // Output: true
console.log(person.hasOwnProperty("address"));    // Output: false

let inheritedObject = Object.create(person);
console.log(inheritedObject.hasOwnProperty("name"));     // Output: false
console.log(inheritedObject.hasOwnProperty("age"));      // Output: false


Takeaways / Best practices:
- Be cautious when using hasOwnProperty() with objects that inherit from other objects, as it only checks for properties directly on the object itself, not those inherited from prototypes.
- Avoid using hasOwnProperty() as the sole check for property existence when dealing with complex object hierarchies or situations involving prototype inheritance. Consider using other techniques like the `in` operator or the `Object.keys()` method.


Removing an object's property using the delete keyword

The `delete` keyword in JavaScript is used to remove a property from an object.

It is used when you want to delete a specific property from an object.

- How is it used?
Here are the steps to remove an object's property using the `delete` keyword:
1. Identify the object from which you want to remove the property.
2. Use the `delete` keyword followed by the object name and the property name you want to delete, separated by a dot (`object.property`).
3. The `delete` keyword will remove the specified property from the object, if it exists.
4. After deleting the property, accessing it will return `undefined`.

Example code snippet:

// Removing an object's property using the delete keyword
let person = {
  name: "John",
  age: 30,
  city: "New York"
};
console.log(person);            // Output: { name: "John", age: 30, city: "New York" }
delete person.age;
console.log(person);             // Output: { name: "John", city: "New York" }
console.log(person.age);      // Output: undefined


Takeaways / Best practices:
- When working with arrays, the `delete` keyword will leave a gap in the array but keep the length intact. It is recommended to use the `Array.prototype.splice()` method to remove elements from an array.


Nested objects

Nested objects refer to objects that are contained within another object. They allow for hierarchical and structured data representation.

Example code snippet:

// Creating and accessing nested objects
let person = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main St",
    city: "New York",
    country: "USA"
  },
  hobbies: ["reading", "traveling"],
  education: {
    degree: "Bachelor's",
    major: "Computer Science"
  }
};

console.log(person.name);                           // Output: John
console.log(person.address.city);                 // Output: New York
console.log(person.hobbies[1]);                   // Output: traveling
console.log(person.education.major);          // Output: Computer Science

// Modifying nested object properties
person.address.city = "San Francisco";
console.log(person.address.city);                   // Output: San Francisco
person.education.major = "Data Science";
console.log(person.education.major);             // Output: Data Science

// Adding a new property to a nested object
person.address.zipCode = "12345";
console.log(person.address.zipCode);            // Output: 12345

// Removing a property from a nested object
delete person.education.degree;
console.log(person.education.degree);           // Output: undefined


Array vs Object

Arrays in JavaScript inherit properties and methods from the Array prototype, which is an object.
When you use the typeof operator on an array, it returns "object". This is because arrays are considered a subtype of objects in JavaScript's type system.

Indices are treated as keys and data i.e. elements as values.
The `Array.isArray()` method is a built-in function in JavaScript used to check if a value is an array.
The method will return `true` if the value is an array, and `false` otherwise.

Code snippet:

const value1 = [1, 2, 3];
const value2 = {};

console.log(Array.isArray(value1)); // Output: true
console.log(Array.isArray(value2)); // Output: false


Array of objects

Array of objects is commonly used when you need to work with a collection of related objects. It is frequently used in scenarios such as managing lists of user data, storing product information, handling data from APIs, etc.

Code snippet:

// Declare an array of objects
const students = [
  { name: 'Alice', age: 20 },
  { name: 'Bob', age: 22 },
  { name: 'Charlie', age: 19 }
];

// Accessing object properties
console.log(students[0].name); // Output: 'Alice'
console.log(students[1].age); // Output: 22

// Modifying object properties
students[2].age = 21;
console.log(students[2].age); // Output: 21

// Adding new objects to the array
students.push({ name: 'David', age: 18 });
console.log(students.length); // Output: 4

// Iterating over the array
for (let i = 0; i < students.length; i++) {
  console.log(students[i].name);
}

/* Output:
Alice
Bob
Charlie
David
*/


In the code snippet, an array named `students` is created, which holds objects representing student data. Object properties like `name` and `age` can be accessed using index notation (`students[index].property`) or manipulated as needed. New objects can also be added to the array using the `push()` method. Finally, the array can be iterated over using a loop to perform operations on each object.


Topic 21: Destructuring

Array Destructuring

Array destructuring is a feature in JavaScript that allows you to extract values from an array and assign them to variables in a concise and structured way.

- How is it used?
Here are the steps to use array destructuring:
1. Declare variables to hold the values extracted from the array.
2. Enclose the variable names within square brackets `[ ]`.
3. Assign the array to be destructured on the right side of the assignment (`=`) operator.
4. The values from the array will be assigned to the variables based on their positions.

Code snippet:

// Array destructuring
const numbers = [1, 2, 3];
const [a, b, c] = numbers;
console.log(a); // Output: 1
console.log(b); // Output: 2
console.log(c); // Output: 3


Takeaways / Best practices:
- Ensure the number of variables on the left side matches the number of elements in the array to avoid undefined values.
- You can skip elements in the array by leaving an empty space in the destructuring pattern (e.g., `[a, , c]`).


Object Destructuring

Object destructuring is a feature in JavaScript that allows you to extract properties from an object and assign them to variables in a concise and structured way.

- How is it used?
Here are the steps to use object destructuring:
1. Declare variables to hold the property values extracted from the object.
2. Enclose the variable names within curly braces `{ }`.
3. Assign the object to be destructured on the right side of the assignment (`=`) operator.
4. The values of the specified object properties will be assigned to the variables with corresponding names.

Code snippet:

// Object destructuring
const person = {
  name: 'John',
  age: 25,
  city: 'New York'
};
const { name, age, city } = person;
console.log(name);   // Output: 'John'
console.log(age);      // Output: 25
console.log(city); // Output: 'New York'


Topic 22: Floating Point Numbers

Floating Point Numbers

Floating-point numbers, also known as floats, are a data type in JavaScript used to represent decimal numbers with fractional parts.

Floating-point numbers are used in various contexts, including mathematical calculations, financial applications, scientific computations, and any scenario where precise decimal representations are required.

Floating-point numbers are represented using the IEEE 754 standard, which specifies the format for storing and performing operations on floats.
Floating-point numbers have limited precision due to the finite number of bits allocated for their representation. This can lead to rounding errors and imprecise results in certain calculations.
Due to the binary representation of floating-point numbers, certain decimal values cannot be represented exactly. This can lead to unexpected results, such as precision errors and comparisons that do not yield the expected outcome.

Code snippet:

const num1 = 0.1;
const num2 = 0.2;
const sum = num1 + num2;

console.log(sum); // Output: 0.30000000000000004

In the code snippet, the sum of `0.1` and `0.2` should ideally be `0.3`. However, due to the limitations of floating-point representation, the result is not exact and contains a small rounding error.


Topic 23: Special Numbers

Special Numbers

Special numbers in JavaScript refer to the non-numeric values that have specific meanings and uses within the language, including NaN, Infinity, and -Infinity.

Special numbers are used in various scenarios, such as error handling, mathematical operations, and representing certain conditions or states in JavaScript programs.

- How is it used?
Here are some key points to understand about special numbers in JavaScript:
1. NaN (Not-a-Number): NaN is a special value representing the result of an invalid or undefined mathematical operation, such as dividing zero by zero or trying to perform arithmetic with non-numeric values.
2. Infinity and -Infinity: Infinity represents a value that is greater than any other number, while -Infinity represents a value that is smaller than any other number. These values can result from operations like dividing a non-zero number by zero or exceeding the maximum representable number.

Code snippet:

const result = 10 / 'abc';
console.log(result); // Output: NaN
console.log(isNaN(result)); // Output: true

const infinityValue = 1 / 0;
console.log(infinityValue); // Output: Infinity
console.log(isFinite(infinityValue)); // Output: false

const NegativeInfinityValue = -1 / 0;
console.log(NegativeInfinityValue ); // Output: -Infinity
console.log(isFinite(NegativeInfinityValue )); // Output: false

Takeaways / Best practices:
- Use the `isNaN()` function to check for NaN values before performing calculations or comparisons.
- Use the `isFinite()` function to determine if a value is a finite number.


Topic 24: Math Functions

trunc() method

trunc() is a method in JavaScript that returns the integer part of a number by removing any fractional digits.

Code snippet example:

let number = 3.14159;
let result = Math.trunc(number);
console.log(result); // Output: 3

Takeaways / Best Practices:
- Be aware that trunc() works based on the sign of the number. Positive numbers are rounded towards zero, while negative numbers are rounded away from zero.
- Remember that trunc() only removes the decimal part and doesn't perform any rounding. If you need rounding, consider using Math.round(), Math.floor(), or Math.ceil() methods instead, depending on your specific requirements.


round() method

round() is a method in JavaScript that returns the nearest integer of a number by rounding it to the nearest whole number.

If the fractional part of the number is less than 0.5, the result will be rounded down to the lower whole number. If the fractional part is 0.5 or greater, the result will be rounded up to the higher whole number.
The returned value will be of the same sign as the original number.

Code snippet example:

let number = 3.7;
let result = Math.round(number);
console.log(result); // Output: 4

Takeaways / Best Practices:
- Be aware that round() can introduce inaccuracies in certain cases due to the inherent limitations of representing floating-point numbers. Keep this in mind when performing precise calculations.


floor() method

floor() is a method in JavaScript that returns the largest integer less than or equal to a given number.

Code snippet example:

let number = 3.9;
let result = Math.floor(number);
console.log(result); // Output: 3

Takeaways / Best Practices:
- Be aware that floor() works based on the sign of the number. Positive numbers are rounded down towards zero, while negative numbers are rounded towards more negative values.
- If you need to round a number to the nearest whole number (either up or down), consider using the round() method instead.


abs() method

abs() is a method in JavaScript that returns the absolute value of a number, which is the positive magnitude of the number without regard to its sign.

Code snippet example:

let number = -5;
let result = Math.abs(number);
console.log(result); // Output: 5


Takeaways / Best Practices:
- abs() is useful in scenarios where you want to ensure positive values for calculations, such as finding the difference between two numbers, comparing distances, or determining magnitudes.
- Remember that abs() only removes the negative sign and returns the positive magnitude; it does not perform any rounding or other transformations on the number itself.
- Take note that abs() can also be used with non-numeric values, such as converting a string representation of a number to its absolute value.
- Use caution when using abs() with non-numeric values, as it will return NaN (Not a Number) for non-convertible values.


sqrt() method

sqrt() is a method in JavaScript that returns the square root of a non-negative number.

sqrt() is commonly used in mathematical calculations involving geometry, physics, and numerical analysis, as well as when you need to manipulate or extract information from data that involves square roots.

Code snippet example:

let number = 16;
let result = Math.sqrt(number);
console.log(result); // Output: 4

Takeaways / Best Practices:
- Be mindful that sqrt() only works with non-negative numbers. If you provide a negative number, it will return NaN.


Topic 25: Function Expressions

Function Expressions

Function Expressions in JavaScript refer to defining a function as a part of an expression, typically by assigning it to a variable.

- They are used in JavaScript when you need to create functions dynamically or when functions need to be assigned or passed as values.
- Function expressions are commonly used in scenarios such as callbacks, closures, and creating self-invoking functions.

Here's how function expressions are used:
1. Define a function as a part of an expression, usually by assigning it to a variable.
2. The function can be named or anonymous (without a specific name).
3. The function expression can be invoked using the assigned variable or passed as an argument to another function.

Code snippet example 1:

// Named function expression
let greet = function sayHello() {
  console.log("Hello!");
};

greet();      // Output: Hello!
sayHello();   // Error: sayHello is not defined


Code snippet example 2:


// Anonymous function expression
let add = function(x, y) {
  return x + y;
};

let result = add(5, 3);
console.log(result); // Output: 8

// Function expression as a callback
function doSomething(callback) {
  console.log("Doing something...");
  callback();
}

doSomething(function() {
  console.log("Callback function executed!");
});

/*Output:

8
Doing something...
Callback function executed!  */

Takeaways / Best Practices:
- Function expressions provide flexibility and can be assigned to variables, passed as arguments, or used as callbacks.
- Named function expressions can be useful for self-reference within the function body but are generally less common.
- Anonymous function expressions are widely used, especially for one-time or inline functions.
- When working with function expressions, consider using descriptive variable names and maintain a clear and readable code structure.


Topic 26: Arrow Functions

Arrow Functions

Arrow Functions in JavaScript are a concise syntax for defining functions that preserve the lexical scope of the surrounding context and provide implicit returns.

- They are used in JavaScript when you need to create shorter and more readable function expressions.
- Arrow functions are commonly used in scenarios such as callbacks, array methods (e.g., map, filter), and when you want to preserve the value of `this` from the surrounding context.

Here's how arrow functions are used:
1. Use the arrow (`=>`) syntax to define the function expression.
2. The arrow function can have zero or more parameters enclosed in parentheses, followed by the arrow (`=>`), and then the function body.
3. If the function body consists of a single expression, it is implicitly returned.
4. If the function body requires multiple statements, use curly braces `{}` and explicitly return the value if needed.

Code snippet example:

// Arrow function with no parameters
let greet = () => {
  console.log("Hello!");
};
greet(); // Output: Hello!

// Arrow function with a single parameter
let double = (num) => num * 2;
console.log(double(5)); // Output: 10

// Arrow function with multiple parameters and explicit return
let add = (x, y) => {
  return x + y;
};
console.log(add(3, 4)); // Output: 7

// Arrow function as a callback
let numbers = [1, 2, 3, 4, 5];
let doubledNumbers = numbers.map((num) => num * 2);
console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]


Takeaways / Best Practices:
- They implicitly bind the surrounding lexical scope, so `this` inside an arrow function refers to the value of `this` in the surrounding context.
- When the function body consists of a single expression, it can be returned implicitly without the need for a `return` keyword.
- Use arrow functions for short, one-line expressions, and prefer traditional function expressions for more complex or multi-line functions.
- Be cautious when using arrow functions as methods within objects, as they don't have their own `this` binding and may not behave as expected.


Topic 27: Pass-by-value and Pass-by-reference

Pass by Value

Pass by Value in JavaScript means that when assigning a value to a variable or passing it as an argument to a function, a copy of the value is created and assigned rather than directly manipulating the original value.

- It is used in JavaScript when working with primitive data types such as numbers, strings, booleans, where the value itself is assigned and manipulated.
- Pass by Value is the default behavior in JavaScript for primitive data types.

Here's how Pass by Value works:
1. When a value is assigned to a variable or passed as an argument to a function, a copy of the value is created.
2. Any changes made to the copy do not affect the original value.
3. The copy and the original value are separate entities in memory.

Code snippet example:

function updateValue(value) {
  value = value * 2;
  console.log("Inside function:", value);
}

let number = 5;
console.log("Before function:", number);
updateValue(number);
console.log("After function:", number);

/* Output:

Before function: 5
Inside function: 10
After function: 5    */


Takeaways / Best Practices:
- Pass by Value is the default behavior for primitive data types in JavaScript.
- Be mindful of the distinction between primitive data types (pass by value) and reference data types (pass by reference) when working with functions and manipulating values in JavaScript.


Pass by Reference

Pass by Reference in JavaScript means that when assigning an object to a variable or passing it as an argument to a function, a reference to the object is passed rather than creating a copy, allowing direct manipulation of the original object.

It is used in JavaScript when working with reference data types such as objects and arrays, where the reference to the object in memory is passed and can be modified.

Here's how Pass by Reference works:
1. When an object is assigned to a variable or passed as an argument to a function, a reference to the object in memory is passed.
2. Changes made to the object through the reference directly modify the original object.

Code snippet example:

function updateValue(obj) {
  obj.value = obj.value * 2;
  console.log("Inside function:", obj.value);
}

let myObject = { value: 5 };
console.log("Before function:", myObject.value);
updateValue(myObject);
console.log("After function:", myObject.value);

/* Output:

Before function: 5
Inside function: 10
After function: 10  */


Takeaways / Best Practices:
- Pass by Reference is the default behavior for reference data types (objects and arrays) in JavaScript.
- Be aware of the distinction between primitive data types (pass by value) and reference data types (pass by reference) when working with functions and modifying values in JavaScript.
- Exercise caution when passing and manipulating objects as it can lead to unintended side effects and make code harder to reason about. 


Topic 28: Spread Operator

Spread Operator

The Spread Operator in JavaScript is a syntax that allows an iterable (such as an array or string) to be expanded into individual elements, which can be used in places where multiple arguments or elements are expected.

The Spread Operator is commonly used in scenarios such as creating new arrays, combining arrays, cloning objects, and passing multiple arguments to functions.

Here's how the Spread Operator is used:
1. To spread an array: Use the spread operator (`...`) followed by the array name to expand the elements of the array.
2. To spread a string: Use the spread operator (`...`) followed by the string name to expand the characters of the string.
3. To combine arrays: Use the spread operator (`...`) followed by the arrays you want to combine.
4. To clone an object: Use the spread operator (`...`) followed by the object name to create a shallow copy of the object.
5. To pass multiple arguments to a function: Use the spread operator (`...`) followed by the array or iterable containing the values you want to pass.

Code snippet examples:

// Spreading an array
const numbers = [1, 2, 3];
console.log(...numbers); // Output: 1 2 3

// Combining arrays
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const combinedArray = [...array1, ...array2];
console.log(combinedArray); // Output: [1, 2, 3, 4, 5, 6]

// Cloning an object
const originalObject = { name: "John", age: 25 };
const clonedObject = { ...originalObject };
console.log(clonedObject); // Output: { name: "John", age: 25 }

// Passing multiple arguments to a function
const values = [1, 2, 3, 4, 5];
function sum(a, b, c, d, e) {
return a + b + c + d + e;
}
console.log(sum(...values)); // Output: 15


Takeaways / Best Practices:
- When spreading an object, it creates a shallow copy, meaning nested objects are still referenced.
- Be mindful of potential performance implications when spreading large arrays or objects.
- The Spread Operator can greatly simplify code and improve readability, but use it judiciously to avoid excessive nesting or overly complex expressions.


Topic 29: Scope

Global Scope

Global Scope in JavaScript refers to the outermost scope where variables and functions are accessible from anywhere within the JavaScript program.

- It is used in JavaScript to define variables and functions that are accessible throughout the entire codebase.
- Global Scope is created when variables and functions are defined outside of any function or block.

Code snippet example:

// Global variables
let globalVariable = "Hello, world!";

function greet() {
  console.log(globalVariable); // Accessible inside functions
}

greet(); // Output: Hello, world!
console.log(globalVariable); // Output: Hello, world!

// Global function
function globalFunction() {
  console.log("This is a global function.");
}

globalFunction(); // Output: This is a global function.


Takeaways / Best Practices:
- Avoid excessive use of global variables to prevent naming conflicts and maintain code clarity.
- Encapsulate functionality within functions or modules to limit the use of the Global Scope.
- Use modular and organized code structures to minimize the reliance on the Global Scope, promoting code reusability and maintainability.


Local Scope

Local Scope in JavaScript refers to the scope within a block, function, or any other construct that creates a new scope, where variables and functions are accessible only within that specific scope.

They are accessible and modifiable only within the specific block or function where they are defined.

Code snippet example:

// Function Scope
function greet() {
  // Local variable
  let name = "John";
  console.log("Hello, " + name);
}

greet(); // Output: Hello, John

// Trying to access the local variable outside the function
console.log(name); // Error (it will be blank as name is not accessible outside greet function)

// Block Scope
function exampleFunction() {
  if (true) {
    let blockVariable = 'I am a block variable';
    console.log(blockVariable); // Output: I am a block variable
  }
  console.log(blockVariable); // Uncaught ReferenceError: blockVariable is not defined
}

exampleFunction();

Output screenshot (for better clarity):



Takeaways / Best Practices:
- Declare variables with `let` or `const` to ensure block-level scoping, and avoid using the outdated `var` keyword, which has function-level scope.
- Embrace the principles of block scoping and use functions to create smaller, focused scopes, promoting code modularity and reducing the risk of unintended side effects.


Lexical Scope

Lexical Scope is used in JavaScript to determine the accessibility and visibility of variables and functions based on where they are defined in the code.

Here's how Lexical Scope is used in JavaScript:
1. Variables and functions are scoped based on their location within the source code.
2. When a variable or function is referenced, JavaScript searches for its definition within the current scope.
3. If the definition is not found, JavaScript looks in the next outer scope and continues until the definition is found or the global scope is reached.
4. Variables and functions defined in outer scopes are accessible within inner scopes, but not vice versa.

Example code snippet:

function outerFunction() {

  const outerVariable = 'I am an outer variable';
  function innerFunction() {
    console.log(outerVariable); // Output: I am an outer variable
    const innerVariable = 'I am an inner variable';
    console.log(innerVariable); // Output: I am an inner variable
  }
  innerFunction();
}
outerFunction();


Takeaways / Best Practices:
- Avoid naming conflicts by using unique names for variables and functions within each scope.
- Understanding lexical scoping is crucial for debugging and writing maintainable code in JavaScript.


Topic 30: Hoisting

Hoisting

Hoisting in JavaScript is a behavior where variable and function declarations are moved to the top of their containing scope during the compilation phase, allowing them to be used before they are actually declared.

Hoisting is applicable to variable and function declarations and is a feature of JavaScript's compilation process.

Here's how Hoisting is used in JavaScript:
1. During the compilation phase, JavaScript moves variable declarations (not assignments) and function declarations to the top of their containing scope.
2. Variable declarations are hoisted but not their assignments. Therefore, variables are accessible but undefined until they are assigned a value.
3. Function declarations are fully hoisted, allowing them to be called before their actual declaration in the code.
4. Function expressions (anonymous functions assigned to variables) are not hoisted.

Example code snippet:

console.log(myVariable); // Output: undefined
var myVariable = 'I am hoisted';

hoistedFunction(); // Output: I am a hoisted function

function hoistedFunction() {
  console.log('I am a hoisted function');
}

notHoistedFunction(); // Error: notHoistedFunction is not a function

var notHoistedFunction = function() {
  console.log('I am not hoisted');
};


Takeaways / Best Practices:
- Declare variables at the top of their scope to avoid confusion and ensure proper initialization.
- Avoid relying on hoisting for readability and code clarity. Declare variables and functions before using them.
- Be aware of the differences between function declarations and function expressions in terms of hoisting behavior.


Topic 31: let vs var vs const

let vs var vs const

let, var, and const are keywords used for variable declaration in JavaScript, each with different scoping and mutability characteristics.

1. let: It declares a block-scoped variable that can be reassigned.
2. var: It declares a function-scoped variable that can be reassigned.
3. const: It declares a block-scoped variable that cannot be reassigned (it is read-only).

These keywords are used in JavaScript to define variables in different contexts based on their scoping and mutability requirements.

Here's how they are used in JavaScript:
- let:
  1. Use `let` to declare variables that are block-scoped, meaning they exist only within the block of code where they are defined.
  2. `let` variables can be reassigned to different values within their scope.
  3. Use `let` when you need to reassign the variable or when you want to limit its scope to a specific block of code.
- var:
  1. Use `var` to declare variables that are function-scoped, meaning they exist throughout the entire function in which they are defined.
  2. `var` variables can be reassigned and redeclared within their function scope.
  3. However, avoid using `var` whenever possible, as it can lead to unexpected behavior due to its hoisting nature and lack of block scoping.
- const:
  1. Use `const` to declare variables that are block-scoped and should not be reassigned.
  2. `const` variables cannot be reassigned after their initial assignment.
  3. Use `const` for values that are meant to remain constant throughout the code or within a specific block.

Example code snippet:

let x = 10; // block-scoped variable with reassignment
var y = 20; // function-scoped variable with reassignment
const z = 30; // block-scoped variable that is read-only

x = 15; // Valid reassignment
y = 25; // Valid reassignment
// z = 35; // Error: Assignment to constant variable

if (true) {
  let blockScoped = 'I am a block-scoped variable';
  var functionScoped = 'I am a function-scoped variable';
  const constant = 'I am a constant variable';
  console.log(blockScoped); // Output: I am a block-scoped variable
}

console.log(functionScoped); // Output: I am a function-scoped variable
// console.log(blockScoped); // Error: blockScoped is not defined


Takeaways / Best Practices:
- Use `let` for variables that need to be reassigned within their block scope.
- Minimize the use of `var` due to its potential for unexpected behavior.
- Use `const` for variables that should not be reassigned.
- Declare variables using the most appropriate keyword based on their intended scope and mutability requirements.
- Consistently use the appropriate keyword throughout your codebase to improve code clarity and maintainability.



Topic 32: Callback

Callback

Callback in JavaScript is a function that is passed as an argument to another function and is executed later, typically after an asynchronous operation completes.


Callbacks are commonly used in JavaScript for handling asynchronous operations like fetching data from a server, reading/writing files, or handling events.


Code snippet example:

// Step 1: Define an asynchronous function

function fetchData(callback) {

  setTimeout(function() {

    const data = { message: "Data fetched successfully" };

    callback(data);   // Step 4: Call the callback function with the fetched data

  }, 2000);
}

// Step 2: Define the callback function

function handleData(data) {

    console.log(data.message);
}

// Step 3: Pass the callback function to the asynchronous function

fetchData(handleData);


Takeaways / Best practices:

- Ensure that the callback function is defined before it is passed as an argument.

- Use meaningful names for both the asynchronous function and the callback function to improve code readability.

- Handle any potential errors or exceptions inside the callback function.

- Be cautious with callback hell, which occurs when multiple callbacks are nested within each other. Consider using promises or async/await for better code organization.



Topic 33: Closure

Closure

Closure in JavaScript is a combination of a function and the lexical environment within which it was declared, allowing the function to access variables from its outer scope even after the outer function has finished executing.


Where is it used?

Closures are commonly used in JavaScript for creating private variables, encapsulating data, and implementing modules.


How is it used?

1. Define an outer function that contains inner functions.

2. Declare variables within the outer function that you want to be accessible by the inner functions.

3. Return one or more inner functions from the outer function, creating closures that retain access to the outer variables.


Code snippet example:

function outerFunction() {

   var outerVariable = 'I am outer';

function innerFunction() {

   console.log(outerVariable); // Accessing outerVariable from the outer scope
 }
  return innerFunction;
}

  var closure = outerFunction();   // Assign the returned inner function to a variable

  closure();   // Invoke the inner function, which still has access to the outerVariable

 //Output  :  I am outer


Takeaways / Best practices:

- Closures can be used to create private variables and encapsulate data, promoting data privacy and preventing direct access from the outside.

- Be mindful of memory consumption when using closures, as they retain references to the outer variables even after the outer function has finished executing.

- Avoid modifying the values of outer variables within inner functions, as it can lead to unexpected behavior.

- Use closures to implement modules, where you can expose only necessary functions and variables while keeping the rest hidden.

- Understand the concept of the lexical environment and how it affects the scope chain of closures.

- Closures can be powerful but also lead to memory leaks if not handled carefully, so ensure that unnecessary references are released when no longer needed.



Topic 34: Advanced array callback functions

forEach()

`forEach()` is a built-in method in JavaScript used to iterate over an array and execute a provided function for each element in the array.

Here's how `forEach()` is used in JavaScript:
1. Invoke the `forEach()` method on an array, passing a callback function as an argument.
2. The callback function is executed once for each element in the array.
3. The callback function can take up to three parameters: the current element, the index of the current element, and the array itself.
4. Within the callback function, perform the desired action or operation on the current element.
5. The `forEach()` method does not return a new array; it simply iterates over the existing array.

Example code snippet:

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

numbers.forEach(function(element, index, array) {
  console.log(`Element: ${element}, Index: ${index}, Array: ${array}`);
  // Perform desired action or operation on the element
});

/* Output:
 Element: 1, Index: 0, Array: 1,2,3,4,5
 Element: 2, Index: 1, Array: 1,2,3,4,5
 Element: 3, Index: 2, Array: 1,2,3,4,5
 Element: 4, Index: 3, Array: 1,2,3,4,5
 Element: 5, Index: 4, Array: 1,2,3,4,5  */


Takeaways / Best Practices:
- The callback function passed to `forEach()` can be an anonymous function or a named function.


find()

`find()` is a built-in method in JavaScript used to search for the first element in an array that satisfies a given condition, returning the value of the element.

Here's how `find()` is used in JavaScript:
1. Invoke the `find()` method on an array, passing a callback function as an argument.
2. The callback function is executed once for each element in the array until a matching element is found or the entire array has been traversed.
3. The callback function takes three parameters: the current element, the index of the current element, and the array itself.
4. Within the callback function, specify the condition that should be met for an element to be considered a match.
5. If a matching element is found, the `find()` method returns the value of that element; otherwise, it returns undefined.

Example code snippet:

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

const foundElement = numbers.find(function(element) {
  return element > 3; // Condition: Find the first element greater than 3
});

console.log(foundElement); // Output: 4


Takeaways / Best Practices:
- The callback function passed to `find()` can be an anonymous function or a named function.


Topic 35: Sorting

Sorting is organizing data by rearranging it in a specific order. JavaScript provides an inbuilt method `.sort()` for this purpose.

If we use `.sort()` on an array, it:

  • Sorts the array in place.
  • Returns a sorted array and the array on which `.sort()` is called is also modified.


Syntax:

array.sort(comparator);
  • `comparator` is an optional function that determines the order of elements in the array.


Sorting array of strings

Sorting an array of strings in JavaScript refers to arranging the strings in a specific order, typically in alphabetical or lexicographical order.

Example code snippet:

const fruits = ['apple',  'date', 'banana', 'cherry' ];

// Sorting in lexicographical order
fruits.sort();

console.log(fruits); // Output: ["apple", "banana", "cherry", "date"]

Takeaways / Best Practices:
- By default, `sort()` arranges the strings in lexicographical order.
- Be mindful of the Unicode code point values when sorting strings, as it may affect the desired sorting outcome.


Sorting array of numbers

Sorting an array of numbers in JavaScript refers to arranging the numbers in a specific order, such as ascending or descending numerical value.

Here's how to sort an array of numbers in JavaScript:
1. Invoke the `sort()` method on the array of numbers.
2. By default, the `sort()` method sorts the numbers as strings based on their Unicode code point values, which may not yield the expected result for numbers.
3. To sort the numbers in numerical order, provide a compare function as an argument to the `sort()` method.
- The compare function should take two number parameters (a and b) and return a negative value if a should be placed before b, a positive value if b should be placed before a, or 0 if the order remains unchanged.
- The compare function can be written inline as an anonymous function or as a separate named function.
4. Once the array is sorted, you can access the sorted elements using their respective indices.

Example code snippet:

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

// Sorting in ascending order
numbers.sort(function(a, b) {
  return a - b;
});

console.log(numbers); // Output: [1, 2, 3, 4, 5]

// Sorting in descending order
numbers.sort(function(a, b) {
  return b - a;
});

console.log(numbers); // Output: [5, 4, 3, 2, 1]


Takeaways / Best Practices:
- Be mindful of potential edge cases, such as handling `NaN` or `Infinity` values, if they exist in the array.
- Always consider the specific sorting requirements and adjust the compare function accordingly.
- To sort an array of objects based on a numerical property, use the compare function to specify the property to sort on (e.g., a.age - b.age for sorting objects by their "age" property).


Sorting array of objects

An array of objects is a collection of objects. Consider the following array of objects:

const items = [

  { name: "Alpha", value: 23 },
  { name: "Bravo", value: 42 },
  { name: "Echo", value: 31 },
  { name: "Foxtrot", value: 56 },
  { name: "Charlie", value: 17 },
  { name: "Delta", value: -9 },

];

Sorting array of objects by numbers


To sort the array based on the `value` property, use the `.sort()` method with a comparator function:

items.sort((a, b) => a.value - b.value);

items.forEach((e) => {

  console.log(`${e.name} ${e.value}`);

});


/* Output

Delta -9
Charlie 17
Alpha 23
Echo 31
Bravo 42
Foxtrot 56

*/

In this example, the comparator function `(a, b) => a.value - b.value` compares the `value` properties of two objects in the `items` array and returns a positive number if the first value is greater than the second value, otherwise a negative number.


Sorting array of objects by strings


To sort the array based on the `name` property, use the `localeCompare` method for string comparison:

items.sort((a, b) => a.name.localeCompare(b.name));

items.forEach((e) => {

  console.log(`${e.name} ${e.value}`);

});


/* Output

Alpha 23
Bravo 42
Charlie 17
Delta -9
Echo 31
Foxtrot 56

*/

Explanation of `localeCompare`


The `localeCompare` method compares two strings in the current locale. The locale is based on the language settings of the browser. This method returns:

  • A negative number if `a` comes before `b` in the sort order.
  • A positive number if `a` comes after `b` in the sort order.
  • 0 if the two strings are considered equal.


Using `localeCompare` ensures that string comparisons are done according to the language-specific rules, which can be important for correctly sorting strings in different languages or with special characters.


Takeaways / Best Practices:

  • Be mindful of potential edge cases, such as handling `NaN` or `Infinity` values, if they exist in the array.
  • Always consider the specific sorting requirements and adjust the compare function accordingly.
  • Use `localeCompare` for sorting strings to handle locale-specific order correctly.



Topic 36: Higher Order Functions

map()

`map()` is a built-in method in JavaScript used to create a new array by applying a provided function to each element of an existing array.

`map()` is commonly used in JavaScript when you need to transform or manipulate each element of an array and generate a new array with the modified values.

Here's how `map()` is used in JavaScript:
1. Invoke the `map()` method on an array, passing a callback function as an argument.
2. The callback function is executed once for each element in the array.
3. The callback function takes three parameters: the current element, the index of the current element, and the array itself.
4. Within the callback function, perform the desired transformation or manipulation on the current element.
5. The `map()` method returns a new array containing the results of the callback function for each element in the original array.
6. The original array remains unchanged.

Example code snippet:

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

const squaredNumbers = numbers.map(function(element) {
  return element * element; // Square each number
});

console.log(squaredNumbers); // Output: [1, 4, 9, 16, 25]

Takeaways / Best Practices:
- The callback function passed to `map()` can be an anonymous function or a named function.
- The `map()` method does not modify the original array; it returns a new array.
- Consider using `map()` in combination with other array methods, such as `filter()`, `reduce()`, or `forEach()`, to achieve more complex transformations and operations on arrays.


filter()

`filter()` is a built-in method in JavaScript used when you need to extract a subset of elements from an array based on a specific criterion or condition.

Here's how `filter()` is used in JavaScript:
1. Invoke the `filter()` method on an array, passing a callback function as an argument.
2. The callback function is executed once for each element in the array.
3. The callback function takes three parameters: the current element, the index of the current element, and the array itself.
4. Within the callback function, define the condition that an element must satisfy to be included in the new array.
5. The `filter()` method returns a new array containing only the elements that pass the condition specified in the callback function.
6. The original array remains unchanged.

Example code snippet:

const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(function(element) {
  return element % 2 === 0; // Filter out odd numbers
});
console.log(evenNumbers); // Output: [2, 4]

Takeaways / Best Practices:
- The callback function passed to `filter()` can be an anonymous function or a named function.
- The `filter()` method does not modify the original array; it returns a new array.
- Consider using `filter()` in combination with other array methods, such as `map()` or `reduce()`, to achieve more complex filtering and data transformation tasks.


reduce()

`reduce()` is a built-in method in JavaScript used to apply a specified function to reduce an array to a single value.

`reduce()` is commonly used in JavaScript when you need to perform calculations or aggregations on the elements of an array and obtain a single result.

Here's how `reduce()` is used in JavaScript:
1. Invoke the reduce() method on an array, passing a callback function and an optional initial value as arguments.
2. The callback function is executed once for each element in the array.
3. The callback function takes four parameters: an accumulator, the current element, the index of the current element, and the array itself.
4. Within the callback function, perform the desired operation using the accumulator and the current element.
5. The result of each iteration is stored in the accumulator.
6. At the end of the reduction process, the `reduce()` method returns the final value of the accumulator.
7. If an initial value is provided as the second argument to `reduce()`, it is used as the initial value of the accumulator; otherwise, the first element of the array is used as the initial value.
8. The original array remains unchanged.

Example code snippet:

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce(function(accumulator, element) {
  return accumulator + element; // Calculate the sum of all numbers
}, 0); // Initial value of the accumulator is 0
console.log(sum); // Output: 15

Takeaways / Best Practices:
- Use `reduce()` to apply a specified function and reduce an array to a single value.
- The callback function passed to `reduce()` can be an anonymous function or a named function.
- Access the accumulator, current element, index, or the entire array within the callback function as needed.
- Ensure that the operation performed in the callback function is consistent and commutative to obtain the desired result.
- Provide an initial value to the `reduce()` method to handle empty arrays or define a specific starting point for the reduction process.
- Consider using `reduce()` for calculations, aggregations, finding maximum or minimum values, or any operation that requires reducing an array to a single value.


Topic 37: Advanced array methods

splice()

`splice()` is a built-in method in JavaScript used to change the contents of an array by removing or replacing existing elements and/or adding new elements.

Here's how `splice()` is used in JavaScript:
1. Invoke the `splice()` method on an array, specifying the starting index and the number of elements to be removed (if any).
2. Optionally, specify new elements to be inserted at the specified index.
3. The `splice()` method modifies the original array and returns an array containing the removed elements (if any).
4. If only the starting index is provided without the count of elements to be removed, all elements from the starting index till the end of the array will be removed.
5. If new elements are provided, they will be inserted at the specified index.
6. The original array is updated with the modified contents.

Example code snippet:

const fruits = ['apple', 'banana', 'cherry', 'date'];

// Removing elements using splice()
const removedElements = fruits.splice(1, 2); // Remove 2 elements starting from index 1
console.log(removedElements); // Output: ["banana", "cherry"]
console.log(fruits); // Output: ["apple", "date"]

// Replacing elements using splice()
fruits.splice(1, 0, 'blueberry', 'grape'); // Insert new elements starting from index 1
console.log(fruits); // Output: ["apple", "blueberry", "grape", "date"]

// Adding and removing elements using splice()
const removedAndInsertedElements = fruits.splice(2, 1, 'kiwi', 'mango'); // Remove 1 element at index 2 and insert new elements
console.log(removedAndInsertedElements); // Output: ["grape"]
console.log(fruits); // Output: ["apple", "blueberry", "kiwi", "mango", "date"]


Takeaways / Best Practices:
- The `splice()` method modifies the original array; it also returns an array containing the removed elements (if any).
- If new elements are provided, they will be inserted at the specified index.
- Consider using `slice()` if you only need to extract a portion of an array without modifying the original array.


slice()

`slice()` is a built-in method in JavaScript used to extract a portion of an array and return a new array containing the selected elements.

Here's how `slice()` is used in JavaScript:
1. Invoke the `slice()` method on an array, specifying the starting and ending indices (optional) as arguments.
2. The `slice()` method returns a new array containing the selected elements.
3. If only the starting index is provided, `slice()` will extract elements from the starting index till the end of the array.
4. If both the starting and ending indices are provided, `slice()` will extract elements from the starting index up to, but not including, the ending index.
5. The original array remains unchanged.

Example code snippet:

const fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];

const selectedFruits = fruits.slice(1, 4); // Extract elements from index 1 to index 3
console.log(selectedFruits); // Output: ["banana", "cherry", "date"]

const lastTwoFruits = fruits.slice(-2); // Extract the last two elements
console.log(lastTwoFruits); // Output: ["date", "elderberry"]

const copyOfFruits = fruits.slice(); // Create a shallow copy of the entire array
console.log(copyOfFruits); // Output: ["apple", "banana", "cherry", "date", "elderberry"]


Takeaways / Best Practices:
- Negative indices can be used to extract elements from the end of the array.
- Calling `slice()` without any arguments creates a shallow copy of the entire array.
- Remember that `slice()` returns a new array, so any modifications to the original or sliced array will not affect each other.


All the best and Happy Learning!




Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article