JavaScript Basics
JavaScript Basics

JavaScript Basics

Updated
Feb 15, 2024 02:53 PM
Category
Programing
Status
Closed

Comment Code


There are two ways to write comments in JavaScript:
Using // will tell JavaScript to ignore the remainder of the text on the current line. This is an in-line comment:
// This is an in-line comment.
You can make a multi-line comment beginning with /* and ending with */. This is a multi-line comment:
/* This is a
multi-line comment */

Variables


Variables are used to store data values. JavaScript variables can hold any data type, and their values can be changed during runtime. In this guide, we'll cover everything you need to know about variables in JavaScript.

Variable Declaration

In JavaScript, variables are declared using the let, const, or var keyword, followed by the variable name. For example:
let x;
const y = 10;
var z = "hello";
  • The let keyword is used to declare a variable that can be reassigned a new value.
  • The const keyword is used to declare a variable that cannot be reassigned a new value once it has been assigned.
  • The var keyword is the old way of declaring variables in JavaScript, but it still works. However, let and const are preferred because they have block scope.
Learn more about the var declaration

Variable Naming

In JavaScript, variable names must begin with a letter, underscore (_), or dollar sign ($). After the first character, variable names can also contain numbers. Variable names are case-sensitive, so myVar and myvar are two different variables.
It's important to choose meaningful variable names that describe the data they store. For example:
let firstName = "John";
const age = 30;
var isStudent = true;

Variable Assignment

Variables in JavaScript can be assigned a value using the assignment operator (=). For example:
let x;
x = 5;
Variables can also be declared and assigned a value in the same statement:
let y = 10;
const message = "Hello, world!";
var z = true;
Multiple variables can be declared and assigned values in a single statement, using commas to separate them:
let a = 1, b = 2, c = 3;

Data Types


Data Type
Description
Example
Number
Represents numerical values, including integers and floating-point numbers.
3, 3.14, 0xff
String
Represents textual data. Strings are enclosed in quotes (single or double).
"hello", 'world', "123"
Boolean
Represents a logical value, either true or false.
true, false
Undefined
Represents the absence of a value or an uninitialized variable.
let x;
Null
Represents the intentional absence of any object value.
null
Symbol
Represents a unique identifier. Symbols are immutable and are often used as keys in objects.
Symbol('foo')
Object
Represents a collection of properties, where each property has a name and a value. Objects can be created using object literals, constructor functions, or the Object() constructor.
{name: 'John', age: 30}, new Date()
Array
A type of object that represents an ordered collection of values, where each value can be accessed using its index. Arrays can be created using array literals or the Array() constructor.
[1, 2, 3], new Array(4)
Function
Represents a reusable block of code that performs a specific task. Functions can be created using function declarations, function expressions, or arrow functions.
function add(a, b) { return a + b; }, () => console.log('Hello, world!')

Operators


JavaScript operators are symbols used to perform operations on values and variables. They allow you to manipulate data, compare values, and perform mathematical operations, among other things. Here's an overview of the different types of operators in JavaScript:

Arithmetic Operators

Arithmetic operators perform basic mathematical operations:
  • + : Addition
  • - : Subtraction
  • * : Multiplication
  • / : Division
  • % : Modulus (remainder)
  • ++ : Increment
  • -- : Decrement
let a = 10;
let b = 3;

console.log(a + b); // 13
console.log(a - b); // 7
console.log(a * b); // 30
console.log(a / b); // 3.333...
console.log(a % b); // 1

Comparison Operators

Comparison operators compare two values and return a boolean result (true or false):
  • ==: Equal t
  • ===: Strictly equal to (equal value and equal type)
  • !=: Not equal to
  • !==: Not strictly equal to (different value or different type)
  • >: Greater than
  • <: Less than
  • >=: Greater than or equal to
  • <=: Less than or equal to
let x = 5;
let y = "5";

console.log(x == y);  // true
console.log(x === y); // false
console.log(x != y);  // false
console.log(x !== y); // true

Logical Operators

Logical operators are used to combine multiple conditions:
  • &&: Logical AND
  • ||: Logical OR
  • !: Logical NOT
let a = true;
let b = false;

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

Assignment Operators

Assignment operators are used to assign values to variables:
  • = : Assign
  • += : Add and assign
  • = : Subtract and assign
  • *= : Multiply and assign
  • /= : Divide and assign
  • %= : Modulus and assign
let x = 10;

x += 5; // x = x + 5; -> x = 15
x -= 3; // x = x - 3; -> x = 12
x *= 2; // x = x * 2; -> x = 24
x /= 4; // x = x / 4; -> x = 6
x %= 5; // x = x % 5; -> x = 1

String Operators

The + operator can be used to concatenate strings:
let firstName = "John";
let lastName = "Doe";

console.log(firstName + " " + lastName); // "John Doe"
The += operator can also be used for string concatenation:
let fullName = "John";
fullName += " Doe";

console.log(fullName); // "John Doe"

Control Structures


Control structures are essential elements in programming languages that allow you to control the flow of your code based on certain conditions or to perform repetitive tasks. In JavaScript, there are several control structures you should be familiar with:

If Statement

The if statement is used to execute a block of code if a specified condition is true:
let age = 18;

if (age >= 18) {
  console.log("You are an adult.");
}

If-Else Statement

The if-else statement is used to execute one block of code if a condition is true and another block of code if the condition is false:
let age = 16;

if (age >= 18) {
  console.log("You are an adult.");
} else {
  console.log("You are not an adult.");
}

else-If Statement

The else-If statement is used to test multiple conditions and execute different blocks of code based on the first true condition:
let grade = 85;

if (grade >= 90) {
  console.log("You got an A.");
} else if (grade >= 80) {
  console.log("You got a B.");
} else if (grade >= 70) {
  console.log("You got a C.");
} else {
  console.log("You did not pass.");
}

Switch Statement

The switch statement is used to perform different actions based on the value of a variable or expression:
let day = 3;

switch (day) {
  case 0:
    console.log("Sunday");
    break;
  case 1:
    console.log("Monday");
    break;
  case 2:
    console.log("Tuesday");
    break;
  case 3:
    console.log("Wednesday");
    break;
  case 4:
    console.log("Thursday");
    break;
  case 5:
    console.log("Friday");
    break;
  case 6:
    console.log("Saturday");
    break;
  default:
    console.log("Invalid day");
}
In this example, the switch statement checks the value of the day variable and executes the corresponding console.log() statement for the matching case. The break keyword is used to exit the switch statement once a match is found. The default case is executed if none of the other cases match.

For Loop

The for loop is used to repeatedly execute a block of code for a specified number of iterations:
for (let i = 0; i < 5; i++) {
  console.log(i);
}
In this example, the for loop iterates 5 times (from i = 0 to i < 5). The i++ statement increments the value of i by 1 after each iteration.

While Loop

The while loop is used to repeatedly execute a block of code as long as a specified condition is true:
let i = 0;

while (i < 5) {
  console.log(i);
  i++;
}
In this example, the while loop continues to execute the block of code until the value of i is no longer less than 5.

Do-While Loop

The do-while loop is similar to the while loop, but it guarantees that the block of code is executed at least once, even if the condition is false from the start:
let i = 5;

do {
  console.log(i);
  i++;
} while (i < 5);
In this example, the do-while loop executes the block of code once, even though the value of i is not less than 5.

For-In Loop

The for-in loop is used to iterate over the properties of an object, allowing you to access the property names and values:
let person = {
  name: "John",
  age: 30,
  city: "New York"
};

for (let key in person) {
  console.log(key + ": " + person[key]);
}
In this example, the for-in loop iterates over the properties of the person object and outputs both the property name (key) and the corresponding value (person[key]).

For-Of Loop

The for-of loop is used to iterate over iterable objects such as arrays, strings, and other collections:
let fruits = ["apple", "banana", "orange"];

for (let fruit of fruits) {
  console.log(fruit);
}
In this example, the for-of loop iterates over the elements of the fruits array and outputs each element.

Break Statement

The break statement is used to exit a loop or switch statement before the loop/switch is completed:
for (let i = 0; i < 10; i++) {
  if (i === 5) {
    break;
  }
  console.log(i);
}
In this example, the break statement exits the for loop when the value of i reaches 5, so the loop only outputs numbers from 0 to 4.

Continue Statement

The continue statement is used to skip the current iteration of a loop and continue with the next iteration:
for (let i = 0; i < 10; i++) {
  if (i % 2 === 0) {
    continue;
  }
  console.log(i);
}
In this example, the continue statement skips the current iteration when the value of i is even, so the loop only outputs odd numbers from 1 to 9.

Data structures


JavaScript offers various data structures to store and manipulate data.

Objects

Objects in JavaScript are collections of key-value pairs, where keys are strings (property names) and values can be any data type, including other objects or functions. Objects can be created using the object literal syntax:
let person = {
  name: "John",
  age: 30,
  greet: function() {
    console.log("Hello, my name is " + this.name);
  }
};

console.log(person.name); // "John"
person.greet();           // "Hello, my name is John"
In this example, the person object has three properties: name, age, and greet. You can access the object properties using the dot notation (person.name) or the bracket notation (person['name']).
Object Data Manipulation Methods

Accessing Object Information:

  • Dot Notation: is the most common and straightforward way to access an object's properties:
console.log(person.name); // "John"

Bracket Notation

  • Bracket Notation: allows you to access an object's properties using a string, which can be a variable or an expression:
console.log(person["name"]); // "John"

let propertyName = "age";
console.log(person[propertyName]); // 30

let dynamicProperty = "na" + "me";
console.log(person[dynamicProperty]); // "John"

Modifying Objects

  • Add a property:
person.country = "USA";
  • Update a property:
person.age = 31;
  • Delete a property:
delete person.age;

Getting Object Properties

keys(): returns an array of an object's enumerable property names (keys).
This method takes one parameter:
  • obj: The object whose enumerable property names you want to retrieve.
values(): returns an array of the property values:
This method takes one parameter:
  • obj: The object whose enumerable property names you want to retrieve.
entries(): returns an array of an object's key-value pairs:
This method takes one parameter:
  • obj: The object whose enumerable property names you want to retrieve.
let keys = Object.keys(person);
let values = Object.values(person);

for (let i = 0; i < keys.length; i++) {
  console.log(keys[i] + ": " + values[i]);
}

let entries = Object.entries(person);

for (let [key, value] of entries) {
  console.log(key + ": " + value);
}

Checking if a property exists

  • hasOwnProperty(): returns a boolean indicating whether the object has the specified property as its own property.
const person = { firstName: "John", lastName: "Doe", age: 30 };
console.log(person.hasOwnProperty("firstName")); // true
console.log(person.hasOwnProperty("middleName")); // false

Arrays

Arrays are special objects used to store collections of values in an ordered list. Arrays are zero-indexed, and you can access elements in an array using their index number:
let fruits = ["apple", "banana", "orange"];

console.log(fruits[0]); // "apple"
console.log(fruits[2]); // "orange"
Arrays have various built-in methods to manipulate their elements.
Array Data Manipulation Methods

Adding elements:

push(): adds elements to the end of an array.
The push() method modifies the original array without creating a new array. Additionally, it returns the new current length of the array, which reflects the number of elements in the modified array.
unshift(): adds elements to the beginning of an array.
The unshift() method modifies the original array without creating a new array. Additionally, it returns the new current length of the array, which reflects the number of elements in the modified array.
fruits.push("grape"); // ["apple", "banana", "orange", "grape"]
fruits.unshift("strawberry"); // ["strawberry", "apple", "banana", "orange"]

Removing elements:

pop(): removes the last element from an array.
When the pop() method is called, it updates the length of the array, and then returns the removed element. If the array is empty, the pop() method returns undefined .
shift(): removes the first element from an array.
When the shift() method is called, it updates the length of the array, and then returns the removed element. If the array is empty, the pop() method returns undefined
fruits.pop(); // ["apple", "banana"]
fruits.shift(); // ["banana", "orange"]

Reversing and sorting elements:

reverse(): reverses the order of elements in an array.
When the reverse() method is called, returns a reference to the same array.
sort(): sorts the elements of an array.
  • When the sort() method is called, returns a reference to the same array.
  • We can also sort() the array in descending order by passing a comparison function:
    • const numbers = [3, 1, 4, 1, 5, 9];
      numbers.sort((a, b) => b - a);
      console.log(numbers); // [9, 5, 4, 3, 1, 1]
      In the comparison function, we subtract b from a, which will result in a negative value if a is greater than b, a positive value if b is greater than a, and 0 if a and b are equal. This will cause the array to be sorted in descending order.
    • See a mimic of the sort function and how to use the comparation function
 
fruits.reverse(); // ['orange', 'banana', 'apple']
fruits.sort(); // ['apple', 'banana', 'orange']

Slicing and splicing elements:

slice(): creates a new array that contains a portion of an existing array.
This method takes two parameters:
  1. start: The index at which to begin the slicing. This is a zero-based index, so the first element of the array has an index of 0.
  1. end (optional): The index at which to end the slicing. This parameter is also a zero-based index. The slice will include all elements up to, but not including, the element at the end index. If this parameter is not specified, the slice will include all elements from the start index to the end of the array.
splice(): adds/removes elements from an array.
  • Modifies the original array on which it is called.
  • Returns an array containing the removed elements.
  • This method takes three parameters:
      1. start: The index at which to begin the modification. This is a zero-based index, so the first element of the array has an index of 0.
      1. deleteCount (optional): The number of elements to remove from the array starting at the start index. If this parameter is not specified or is greater than the number of elements remaining in the array after the start index, all elements after the start index will be removed.
      1. item1, item2, ... (optional): Any additional items to insert into the array starting at the start index.
let slicedFruits = fruits.slice(1, 3); // ['banana', 'orange']
fruits.splice(1, 0, "kiwi"); // ['apple', 'kiwi', 'banana', 'orange']

Concatenating arrays:

concat(): merges two or more arrays into a new array.
This method takes one or more arrays as its arguments. It returns a new array that contains all the elements of the original arrays in the order in which they are passed to the method.
let vegetables = ["carrot", "broccoli", "spinach"];
let combined = fruits.concat(vegetables); // ['apple', 'banana', 'orange', 'carrot', 'broccoli', 'spinach']

Iterating over elements:

forEach(): executes a provided function once for each element in an array.
This method takes 2 parameters, a callback function and the thisArg Parameter:
  • callback: This is a required parameter, and it's a function that will be executed for each element in the array. The callback function accepts three arguments:
      1. currentValue: The current element being processed in the array.
      1. index (optional): The index of the current element being processed in the array.
      1. array (optional): The array that forEach is being applied to.
  • thisArg: (optional): Allows you to specify the value of this when executing the callback function by a given object. If not provided, this will be undefined.
    • const numbers = [1, 2, 3, 4, 5];
      const multiplier = {
        factor: 3,
        multiply(number) {
          console.log(number * this.factor);
        },
      };
      
      numbers.forEach(multiplier.multiply, multiplier); // Logs 3, 6, 9, 12, 15 to the console
fruits.forEach(function(fruit, index) {         //Fruit 0: apple
  console.log("Fruit " + index + ": " + fruit); //Fruit 1: banana
});                                             //Fruit 2: orange

Searching and filtering elements:

indexOf(): search for an element in an array and returns the first index at which the element is found.
  • If the element is not found in the array, it returns -1.
  • This method takes two parameters:
      1. searchElement: The element to search for in the array.
      1. fromIndex (optional): The index at which to start searching for the element in the array. If not specified, the search starts from index 0.
includes(): determines whether an array includes a certain element.
  • It returns a boolean value, true if the element or substring is found, and false otherwise.
  • This method takes two parameters:
      1. element: The element to search for in the array.
      1. fromIndex (optional): The position in the array from which to start the search. If not provided or if its value is negative or greater than or equal to the length of the array, the entire array will be searched.
find(): returns the first element in the array that satisfies a given condition.
  • The condition is specified using a callback function, which is executed for each element in the array until a match is found. If no match is found, find() returns undefined
  • This method takes 2 parameters, a callback function and the thisArg Parameter:
    • callback: This is a required parameter, and it's a function that is executed for each element in the array. The callback function should return a boolean value, true if the current element satisfies the condition, and false otherwise. The callback function accepts three arguments:
        1. element: The current element being processed in the array.
        1. index (optional): The index of the current element being processed in the array.
        1. array (optional): The array that find() is being applied to.
    • thisArg (optional): Allows you to specify the value of this when executing the callback function by a given object. If not provided, this will be undefined.
filter(): creates a new array with all elements that pass the test implemented by a provided function.
  • Elements that pass the condition (return true in the callback function) are included in the new array, while those that fail (return false) are excluded.
  • This method takes 2 parameters, a callback function and the thisArg Parameter:
    • callback: This is a required parameter, and it's a function that is executed for each element in the array. The callback function should return a boolean value, true if the current element satisfies the condition, and false otherwise. The callback function accepts three arguments:
        1. element: The current element being processed in the array.
        1. index (optional): The index of the current element being processed in the array.
        1. array (optional): The array that filter() is being applied to.
    • thisArg (optional): This parameter allows you to specify the value of this when executing the callback function by a given object. If not provided, this will be undefined.
some(): checks if at least one element in the array satisfies the given condition
This method takes 2 parameters, a callback function and the thisArg Parameter:
  • callback: This is a required parameter, and it's a function that is executed for each element in the array. The callback function should return a boolean value, It returns a boolean value: true if the condition is met by at least one element, and false otherwise. The callback function accepts three arguments:
      1. element: The current element being processed in the array.
      1. index (optional): The index of the current element being processed in the array.
      1. array (optional): The array that filter() is being applied to.
  • thisArg (optional): This parameter allows you to specify the value of this when executing the callback function by a given object. If not provided, this will be undefined.
every() checks if all elements in the array satisfy the given condition
This method takes 2 parameters, a callback function and the thisArg Parameter:
  • callback: This is a required parameter, and it's a function that is executed for each element in the array. The callback function should return a boolean value, It returns a boolean value: true if the condition is met by all elements, and false otherwise. The callback function accepts three arguments:
      1. element: The current element being processed in the array.
      1. index (optional): The index of the current element being processed in the array.
      1. array (optional): The array that filter() is being applied to.
  • thisArg (optional): This parameter allows you to specify the value of this when executing the callback function by a given object. If not provided, this will be undefined.
console.log(fruits.indexOf("banana")); // 1
console.log(fruits.includes("orange")); // true

let foundFruit = fruits.find(fruit => fruit.startsWith("b")); // 'banana'
let filteredFruits = fruits.filter(fruit => fruit.length > 5); // ['banana', 'orange']

let hasApple = fruits.some(fruit => fruit === "banana"); // true
let allFruitsHaveFiveLetters = fruits.every(fruit => fruit.length === 5); // false

Transforming and reducing elements:

map(): creates a new array with the results of calling a provided function on every element in the array.
This method takes 2 parameters, a callback function and the thisArg Parameter:
  1. callback: This is a required parameter, and it's a function that is executed for each element in the array. The callback function should return a value, which will be added to the new array. The callback function accepts three arguments:
      • element: The current element being processed in the array.
      • index (optional): The index of the current element being processed in the array.
      • array (optional): The array that filter() is being applied to.
  1. thisArg (optional): This parameter allows you to specify the value of this when executing the callback function by a given object. If not provided, this will be undefined.
reduce(): applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.
  • It returns the final accumulated value after processing all the elements in the array using the provided callback function.
  • This method takes 2 parameters
      1. callback: This is a required parameter, and it's a function that is executed for each element in the array. The callback function should return the new accumulated value after processing the current element. The callback function accepts four arguments:
          • accumulator: The accumulated value from the previous iteration or the initialValue for the first iteration.
          • currentValue: The current element being processed in the array.
          • index (optional): The index of the current element being processed in the array.
          • array (optional): The array that reduce() is being applied to.
      1. initialValue (optional): This parameter allows you to specify an initial value for the accumulator. If provided, the first iteration will use the initialValue as the accumulator, and the callback function will be executed for every element in the array. If not provided, the first element of the array will be used as the initial value, and the callback function will be executed starting from the second element in the array.
let fruitLengths = fruits.map(fruit => fruit.length); // [5, 6, 6]
let totalLength = fruits.reduce((accumulator, fruit) => accumulator + fruit.length, 0); // 17

Strings

Strings are sequences of characters and are considered iterable:
let text = "Hello, World!";

for (let char of text) {
  console.log(char);
}
In this example, the for-of loop is used to iterate over the characters in the text string.
String Data Manipulation Methods

Getting string length:

  • length: Retrieves the length of a string (the number of characters).
let myString = "Hello, world!";
console.log(myString.length); // 13

Accessing individual characters:

charAt(): Returns the character at a specific index in a string.
This method takes one parameter:
  • index: a zero-based index representing the position of the character you want to retrieve. If the index is negative or greater than or equal to the string's length, the method returns an empty string.
  • [] (bracket notation): Retrieves the character at a specific index in a string using bracket notation.
let character = myString.charAt(7); // "w"
let character = myString[7]; // "w"

Concatenating strings:

concat(): Concatenates two or more strings together.
Can take multiple parameters, these parameters can only be String type and the method will coerce those parameters into strings if other types are passed.
  • + (addition operator): Concatenates two or more strings using the addition operator.
  • ``(Template literals): Concatenates strings using placeholders and expressions inside ${}.
let greeting = "Hello";
let target = "world";

let fullGreeting = greeting.concat(", ", target, "!"); // "Hello, world!"
let fullGreeting = greeting + ", " + target + "!"; // "Hello, world!"
let fullGreeting = `${greeting}, ${target}!`; // "Hello, world!"

Splitting and joining strings:

split(): Splits a string into an array of substrings based on a separator.
This method takes two parameters:
  1. separator (optional): The pattern or character(s) used to split the string. If not provided or set to an empty string, the returned array will contain each character of the original string as a separate element.
  1. limit (optional): A non-negative integer that specifies the maximum number of substrings to include in the resulting array. Any additional substrings will be discarded. If not provided, all substrings will be included in the output.
join(): Joins an array of substrings into a single string based on a separator.
This method takes one parameter:
separator (optional): The character(s) used to separate the elements in the resulting string. If not provided, the default separator is a comma (,).
let sentence = "This is a sentence.";

let words = sentence.split(" "); // ["This", "is", "a", "sentence."]
let joinedSentence = words.join(" "); // "This is a sentence."

Finding substrings:

indexOf(): Finds the first occurrence of a substring in a string and returns the index of the first character of the substring.
  • If the specified element or substring is not found, the method returns -1.
  • This method takes two parameters:
      1. searchValue: The substring you want to search for within the string.
      1. fromIndex (optional): The index from which to start the search. If not provided or a negative value, the search starts at the beginning of the string. If the value is greater than or equal to the length of the string, the method returns -1.
lastIndexOf(): Finds the last occurrence of a substring in a string and returns the index of the first character of the substring.
  • If the specified element or substring is not found, the method returns -1.
  • This method takes two parameters:
      1. searchValue: The substring you want to search for within the string.
      1. fromIndex (optional): The index at which to start the search searching backwards. If not provided, the search starts at the end of the string. If the value is greater than or equal to the length of the string, the search starts at the end of the string.
includes(): Determines whether a string includes a given substring.
  • The method returns a boolean value: true if the specified element or substring is found, and false otherwise.
  • This method takes two parameters:
    • searchValue: The substring you want to search for within the string.
    • position (optional): The index at which to start the search. If not provided, the search starts at the beginning of the string. If the value is negative or greater than the length of the string, the method returns false.
let index = myString.indexOf("world"); // 7
let index = myString.lastIndexOf("o"); // 8
let hasSubstring = myString.includes("world"); // true

Extracting substrings:

slice(): Extracts a substring from a string based on the provided start and end indices, with support for negative indices.
  • A new array or string containing the extracted elements or characters is returned.
  • This method takes two parameters:
      1. beginIndex: The zero-based index at which to start extraction. If negative, it is treated as an offset from the end of the string.
      1. endIndex (optional): The zero-based index before which to end extraction. If not provided, the extraction goes until the end of the string. If negative, it is treated as an offset from the end of the string.
substr(): Extracts a substring from a string based on the provided start index and length.
  • A new array or string containing the extracted elements or characters is returned.
  • This method takes two parameters:
      1. start: The zero-based index at which to start extraction. If negative, it is treated as an offset from the end of the string.
      1. length (optional): The number of characters to extract. If not provided or a negative value, the extraction goes until the end of the string.
let sub = myString.slice(7, 12); // "world"
let sub = myString.substr(7, 5); // "world"

Replacing substrings:

replace(): Replaces the first occurrence of a substring with another substring.
  • A new string with the replaced substring(s) is returned.
  • This method takes two parameters:
      1. searchValue: The substring or regular expression pattern you want to search for within the string.
      1. replaceValue: The substring or a function that returns a string, which will replace the matched substring(s).
        1. If a function is provided
          This function will be called for each match found in the input string, and its return value will be used as the replacement for the matched substring.
          When the replace() method calls the provided function, it passes the following arguments:
          • The matched substring.
          • The matched parenthesized substrings (if any) when using a regular expression with capturing groups.
          • The offset of the matched substring within the string.
          • The whole input string.
          const text = 'I have 3 apples and 5 oranges.';
          const pattern = /(\d+)\s(apples|oranges)/g;
          
          const replaced = text.replace(pattern, function(match, count, fruit, offset, input) {
            // Convert the count to an integer
            const countAsNumber = parseInt(count, 10);
          
            // Determine the correct plural form of the fruit
            const pluralFruit = countAsNumber === 1 ? fruit : fruit + 's';
          
            // Return the replacement string
            return `${countAsNumber * 2} ${pluralFruit}`;
          });
          
          console.log(replaced); // 'I have 6 apples and 10 oranges.'
replaceAll(): Replaces all occurrences of a substring with another substring.
  • A new string with the replaced substring(s) is returned.
  • This method takes two parameters:
      1. searchValue: The substring or regular expression pattern you want to search for within the string.
      1. replaceValue: The substring or a function that returns a string, which will replace the matched substring(s).
      If a function is provided
      This function will be called for each match found in the input string, and its return value will be used as the replacement for the matched substring.
      The arguments passed to the provided function are the same as those passed when using a function with the replace() method:
      • The matched substring.
      • The matched parenthesized substrings (if any) when using a regular expression with capturing groups.
      • The offset of the matched substring within the string.
      • The whole input string.
      Here's an example demonstrating the use of a function as the replaceValue parameter with the replaceAll() method:
      const text = 'Temperature: -10°C, 20°C, 30°C, 15°C';
      const pattern = /(-?\d+)°C/g;
      
      const replaced = text.replaceAll(pattern, function(match, degreesCelsius, offset, input) {
        // Convert Celsius to Fahrenheit
        const degreesFahrenheit = (parseInt(degreesCelsius, 10) * 9) / 5 + 32;
      
        // Return the replacement string with Fahrenheit degrees
        return `${degreesFahrenheit}°F`;
      });
      
      console.log(replaced); // 'Temperature: 14°F, 68°F, 86°F, 59°F'
let newString = myString.replace("world", "everyone"); // "Hello, everyone!"
let newString = myString.replaceAll("o", "O"); // "HellO, wOrld!"

Modifying case:

  • toLowerCase(): Converts a string to lowercase.
  • toUpperCase(): Converts a string to uppercase.
    • notion image
let lowerString = myString.toLowerCase(); // "hello, world!"
let upperString = myString.toUpperCase(); // "HELLO, WORLD!"

Trimming whitespace:

  • trim(): Removes whitespace from both ends of a string.
  • trimStart() / trimLeft(): Removes whitespace from the beginning of a string.
  • trimEnd() / trimRight(): Removes whitespace from the end of a string.
let stringWithWhitespace = "  Hello, world!  ";

let trimmedString = stringWithWhitespace.trim(); // "Hello, world!"
let trimmedStartString = stringWithWhitespace.trimStart(); // "Hello, world!  "
let trimmedEndString = stringWithWhitespace.trimEnd(); // "  Hello, world!"

Escaping special characters:

  • Use a backslash (\) to escape special characters in a string, such as quotes or other escape characters.
let stringWithQuotes = "She said, \"Hello, world!\""; // She said, "Hello, world!"
let stringWithBackslash = "C:\\Users\\username\\Documents"; // C:\Users\username\Document

Maps

Maps are key-value pairs collections similar to objects, but they allow keys of any data type. Maps maintain the insertion order of their elements:
let map = new Map();
map.set("one", 1);
map.set("two", 2);

for (let [key, value] of map) {
  console.log(key + " => " + value);
}
In this example, the for-of loop is used to iterate over the key-value pairs in the map.

Sets

Sets are collections of unique values. They can store values of any data type and maintain the insertion order of their elements:
let set = new Set(["apple", "banana", "orange", "banana"]);

console.log(set) // ["apple", "banana", "orange"]

for (let value of set) {
  console.log(value);
}
In this example, the for-of loop is used to iterate over the unique values in the set.

JavaScript Functions

JavaScript functions are blocks of code that can be defined and called by a name to perform a specific task. Functions help in organizing and reusing code, making it more readable and efficient.

Defining a Function

You can define a function using the function keyword, followed by the function name, parentheses (), and a set of curly braces {}. The code you want to execute is placed inside the curly braces.
function functionName() {
  // code to be executed
}

Calling a Function

To call a function, simply use its name followed by parentheses ().
functionName();

Function Parameters

Functions can take input values called parameters. Parameters are specified inside the parentheses during the function definition.
function functionName(parameter1, parameter2) {
  // code to be executed
}
When calling a function with parameters, you pass the input values, called arguments, inside the parentheses.
functionName(argument1, argument2);

Return Values

Functions can return a value using the return keyword. When a function returns a value, you can use or store that value.
function functionName(parameter1, parameter2) {
  // code to be executed
  return result;
}

const result = functionName(argument1, argument2);

Function Example

JavaScript function that adds two numbers:
// Function definition
function addNumbers(a, b) {
  return a + b;
}

// Function call
const sum = addNumbers(3, 4);

// Output: 7
console.log(sum);
In this example, we defined a function called addNumbers with two parameters a and b. We then called the function with the arguments 3 and 4 and stored the result in a variable called sum. Finally, we logged the result to the console.

Anonymous Functions

An anonymous function is a function without a name. They are often used as arguments for other functions or as a part of a variable assignment. To create an anonymous function, use the function keyword followed by parentheses () and curly braces {} without specifying a name.
const myFunction = function(a, b) {
  return a * b;
};

Arrow Functions

Arrow functions, introduced in ECMAScript 6 (ES6), are a more concise way to write functions. They use the "fat arrow" => syntax.
const myFunction = (a, b) => {
  return a * b;
};
For single-parameter functions, you can omit the parentheses. For single-line functions, you can omit the curly braces and the return keyword.
const square = a => a * a;
square(3)

Scopes

In JavaScript, scope determines the visibility and lifetime of variables. There are three types of scope: global scope, function scope and block scope

Global Scope

A variable declared outside a function or a block has a global scope. It means that the variable can be accessed from any part of the code, including within functions.
const globalVar = "I am global!";

function showGlobalVar() {
  console.log(globalVar);
}

// Output: "I am global!"
showGlobalVar();

// Output: "I am local!"
console.log(globalVar);

Function Scope

A variable declared inside a function has a local scope. It means that the variable is only accessible within that function.
function showLocalVar() {
  const localVar = "I am local!";
  console.log(localVar);
}

// Output: "I am local!"
showLocalVar();

// ReferenceError: localVar is not defined
console.log(localVar);

Block Scope

You can use the let and const keywords to declare variables with block scope. A block is a section of code enclosed by curly braces {}. Block-scoped variables are accessible only within the block they are declared in.
if (true) {
  const blockVar = "I am block scoped!";
}

// ReferenceError: blockVar is not defined
console.log(blockVar);
More Info about var and let block scope differences

Using let in a block

if (true) {
  let blockVar = "I am block scoped with let!";
  console.log(blockVar); // Output: "I am block scoped with let!"
}

// ReferenceError: blockVar is not defined
console.log(blockVar);
In this example, the variable blockVar is declared with let inside a block, so it's only accessible within that block. Trying to access it outside the block results in a ReferenceError.

Using var in a block

if (true) {
  var blockVar = "I am block scoped with var!";
  console.log(blockVar); // Output: "I am block scoped with var!"
}

// Output: "I am block scoped with var!"
console.log(blockVar);
In this example, we use var instead of let to declare the blockVar variable. Since var doesn't have block scope, the variable is accessible both inside and outside the block.

Using let in a loop

for (let i = 0; i < 3; i++) {
  console.log(i); // Output: 0, 1, 2
}

// ReferenceError: i is not defined
console.log(i);
Here, the loop variable i is declared with let, making it block-scoped within the loop. Accessing it outside the loop results in a ReferenceError.

Using var in a loop

for (var i = 0; i < 3; i++) {
  console.log(i); // Output: 0, 1, 2
}

// Output: 3
console.log(i);
In this example, we use var to declare the loop variable i. Since var is function-scoped, the variable i is accessible outside the loop as well.
 

Object Oriented Programming

Object Oriented Programming (OOP) is a programming paradigm that allows you to structure your code by organizing it into "objects" that contain data (atributes) and functions (methods). This can make your code more modular, reusable, and easier to maintain. In JavaScript, OOP can be achieved using objects, classes, and inheritance.

Objects

An object is a collection of key-value pairs, where each key is called a property and each value can be a data type or a function (method). Here's a simple example of an object:
let person = {
  firstName: 'John',
  lastName: 'Doe',
  age: 30,
  greet: function() {
    console.log('Hello, my name is ' + this.firstName + ' ' + this.lastName);
  }
};

person.greet(); // 'this' refers to the 'person' object inside the 'greet' method.
In this example, firstName, lastName, and age are properties, and greet is a method.

Classes

A class is a blueprint for creating objects with similar properties and methods. Classes help you define reusable and modular code. Here's an example of a class:
class Person {
  constructor(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }

  greet() {
    console.log('Hello, my name is ' + this.firstName + ' ' + this.lastName);
  }
}

let john = new Person('John', 'Doe', 30);
jhon.greet()
In this example, the Person class has a constructor that initializes the object's properties and a greet method. To create a new object from the class, we use the new keyword.

Inheritance

Inheritance is a way to create a new class that inherits properties and methods from an existing class. This helps you create more specialized classes without duplicating code. Here's an example:
class Employee extends Person {
  constructor(firstName, lastName, age, position) {
    super(firstName, lastName, age);
    this.position = position;
  }

  introduce() {
    console.log('Hi, I work as a ' + this.position);
  }
}

let jane = new Employee('Jane', 'Smith', 28, 'Software Developer');
In this example, the Employee class inherits from the Person class using the extends keyword. The super keyword is used to call the constructor of the parent class, initializing the properties inherited from Person. We also add a new property position and a new method introduce to the Employee class.

Asynchronous JavaScript

Asynchronous JavaScript allows you to perform tasks without blocking the execution of other code. This is especially useful when dealing with tasks that take time to complete, such as requesting data from a server or reading a file.

Callbacks

A callback function is a function passed as an argument to another function, which is then executed at a later time. Callbacks are a common approach to handling asynchronous tasks in JavaScript.
function fetchData(callback) {
  // Simulate an asynchronous data request using setTimeout
  setTimeout(() => {
    const data = "Here is your data!";
    callback(data, false);
  }, 1000);
}

function processData(data) {
  console.log(`Data processed: ${data}`);
}

// Pass the processData function as a callback
fetchData(processData);
In this example, we use setTimeout to simulate an asynchronous data request. The fetchData function takes a callback function as a parameter, which is then called with the fetched data.

Promises

Promises were introduced in ECMAScript 6 (ES6) to provide a more organized way to handle asynchronous operations. A promise is an object representing the eventual completion (or failure) of an asynchronous operation and its resulting value.
A promise is in one of three states:
  1. Pending: Initial state; neither fulfilled nor rejected.
  1. Fulfilled: The operation completed successfully, and the promise has a resulting value.
  1. Rejected: The operation failed, and the promise has a reason for the failure.
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = "Here is your data!";
      const error = false;

      if (!error) {
        resolve(data);
      } else {
        reject("Error: Data could not be fetched.");
      }
    }, 1000);
  });
}

function processData(data) {
  console.log(`Data processed: ${data}`);
}

function handleFailure(error) {
  console.log(`Error encountered: ${error}`);
}

// Use the .then() method to handle the fulfilled promise and the .catch() method to
// handle the rejected promise
fetchData()
  .then(processData)
  .catch(handleFailure);
In this example, we create a new promise inside the fetchData function. We use setTimeout to simulate an asynchronous data request. We also introduce a simulated error condition with the error variable. If there's no error, we call the resolve function with the fetched data. If there's an error, we call the reject function with an error message. The processData function is then called using the .then() method if the promise is fulfilled, and the handleFailure function is called using the .catch() method if the promise is rejected.

Async/Await

Async/await is a modern syntax introduced in ECMAScript 8 for writing asynchronous code that looks like synchronous code. It's built on top of promises and makes it easier to work with them.
To use async/await:
  1. Declare a function as async.
  1. Use the await keyword inside the async function to wait for a promise to be resolved.
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = "Here is your data!";
      const error = false;

      if (!error) {
        resolve(data);
      } else {
        reject("Error: Data could not be fetched.");
      }
    }, 1000);
  });
}

async function processData() {
  try {
    const data = await fetchData();
    console.log(`Data processed: ${data}`);
  } catch (error) {
    console.log(`Error: ${error}`);
  }
}

// Call the async function
processData();
In this example, we declare the fetchData and processData functions as async. Inside the processData function, we use the await keyword to wait for the promise returned by fetchData to be resolved. The try and catch blocks are used to handle errors.

Regular expressions

Regular expressions (regex) are a powerful tool for working with text patterns in JavaScript and many other programming languages. They are used for searching, matching, and manipulating text based on specific patterns. A regex is essentially a sequence of characters that defines a search pattern.
In JavaScript, regular expressions are represented by the RegExp object, but they can also be written using regex literals, which are enclosed by forward slashes (/pattern/flags).

Creating a regex

You can create a regex using regex literals:
const regexLiteral = /pattern/flags;
Or by using the RegExp constructor:
const regexConstructor = new RegExp('pattern', 'flags');

Regex special characters

  • ^: Start of input.
    • Example: ^Hello matches strings starting with "Hello"
  • $: End of input.
    • Example: World$ matches strings ending with "World"
  • .: Any single character (except newline).
    • Example: H.llo matches "Hello", "Hxllo", "H1llo", etc.
  • *: Zero or more occurrences of the preceding character or group.
    • Example: He*llo matches "Hllo", "Hello", "Heello", "Heeello", etc.
  • +: One or more occurrences of the preceding character or group.
    • Example: He+llo matches "Hello", "Heello", "Heeello", etc., but not "Hllo"
  • ?: Zero or one occurrence of the preceding character or group.
    • Example: He?llo matches "Hllo" and "Hello", but not "Heello"
  • {n}: Exactly n occurrences of the preceding character or group.
    • Example: He{2}llo matches "Heello", but not "Hello" or "Heeello"
  • {n,}: At least n occurrences of the preceding character or group.
    • Example: He{2,}llo matches "Heello", "Heeello", "Heeeello", etc., but not "Hello"
  • {n,m}: Between n and m occurrences of the preceding character or group.
    • Example: He{1,3}llo matches "Hello", "Heello", "Heeello", but not "Hllo" or "Heeeello"
  • []: A character set, matches any character inside the brackets.
    • Example: H[ae]llo matches "Hallo" and "Hello", but not "Hillo"
  • [^]: A negated character set, matches any character NOT inside the brackets.
    • Example: H[^ae]llo matches "Hillo", "Hxllo", "H1llo", etc., but not "Hallo" or "Hello"
  • |: Alternation, matches either the expression before or after the |.
    • Example: Hello|World matches either "Hello" or "World"
  • (): Grouping, groups part of the regex together.
    • Example: (He)+llo matches "Hello", "HeHelloy", but not "Heello"
  • \: Escape character, used to treat special characters as literals.
    • Example: He\.llo matches "He.llo", but not "Heello" or "Hxllo"

Regex flags

There are several flags you can use to modify the behavior of your regex:
  • g: Global search, finds all matches rather than stopping at the first match.
  • i: Case-insensitive search.
  • m: Multiline mode, the ^ and $ characters match the start and end of each line.
  • s: Allows the dot (.) to match newline characters.
  • u: Unicode mode, treats the pattern as a sequence of Unicode code points.
  • y: Sticky mode, matches only from the lastIndex property of the regex.

Regex methods

JavaScript provides several methods for working with regex:
  • RegExp.test(string): Returns true if the regex matches the string, false otherwise.
  • RegExp.exec(string): Returns an array of information about the matched substring, or null if no match is found.
  • String.match(regex): Returns an array of all matches found in the string, or null if no match is found.
  • String.matchAll(regex): Returns an iterator for all match objects found in the string.
  • String.search(regex): Returns the index of the first match in the string, or 1 if no match is found.
  • String.replace(regex, replaceValue): Returns a new string with matched substrings replaced by the replaceValue (a string or a function).
  • String.replaceAll(regex, replaceValue): Returns a new string with all matched substrings replaced by the replaceValue (a string or a function).