Topic 001 : Arrays, Arrow function, Object, Map, Filter, Reduce, Mutability and Immutability, Destructuring
Arrays in JavaScript are a fundamental data structure used to store multiple values in a single variable. They allow you to group together elements of the same type or different types and access them using indices. Here’s a detailed explanation of arrays in JavaScript:
Declaration and Initialization: Arrays in JavaScript can be declared and initialized in several ways:
// Method 1: Using array literal
let myArray = []; // Empty array
let numbers = [1, 2, 3, 4, 5]; // Array with elements
// Method 2: Using the Array constructor
let colors = new Array(); // Empty array
let fruits = new Array("Apple", "Banana", "Orange"); // Array with elements
Accessing Elements: Array elements are accessed using zero-based indices.
let fruits = ["Apple", "Banana", "Orange"];
console.log(fruits[0]); // Output: "Apple"
console.log(fruits[1]); // Output: "Banana"
Properties and Methods: Arrays in JavaScript come with various properties and methods to manipulate them:
length
: Property that returns the number of elements in the array.push()
: Method to add one or more elements to the end of an array.pop()
: Method to remove the last element from an array and return it.shift()
: Method to remove the first element from an array and return it.unshift()
: Method to add one or more elements to the beginning of an array.splice()
: Method to add or remove elements from an array at a specific index.Dynamic Nature: Arrays in JavaScript are dynamic, meaning their size can change dynamically by adding or removing elements.
let fruits = ["Apple", "Banana", "Orange"];
fruits.push("Mango"); // Add an element
fruits.pop(); // Remove the last element
Iteration: You can iterate over arrays using loops like for
loop, forEach()
method, map()
method, etc.
let numbers = [1, 2, 3, 4, 5];
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}
// Using forEach method
numbers.forEach(function(number) {
console.log(number);
});
Multidimensional Arrays: JavaScript arrays can contain other arrays, allowing you to create multidimensional arrays.
let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
console.log(matrix[1][2]); // Output: 6
Arrays are versatile and widely used in JavaScript for various purposes, such as storing collections of data, implementing data structures, and performing operations on collections. Understanding arrays is crucial for any JavaScript developer.
In JavaScript, objects are fundamental data structures used to store and organize data. They are collections of key-value pairs where each key is a unique identifier (often referred to as a property) associated with a value. Objects are versatile and can represent various entities, including real-world objects, abstract concepts, functions, and more. Here’s a detailed breakdown of objects in JavaScript:
Object Literals: One common way to create objects in JavaScript is by using object literals. This involves enclosing key-value pairs within curly braces {}
, with each pair separated by a comma. Here’s an example:
let person = {
name: "John",
age: 30,
isEmployed: true
};
Accessing Properties: You can access properties of an object using either dot notation (object.property
) or bracket notation (object['property']
). Dot notation is more common and concise, but bracket notation is useful when dealing with dynamic property names or properties with special characters.
console.log(person.name); // Output: "John"
console.log(person['age']); // Output: 30
Adding and Modifying Properties: You can add new properties to an object or modify existing ones at any time by simply assigning values to them.
person.gender = "Male"; // Adding a new property
person.age = 31; // Modifying an existing property
Deleting Properties: You can remove properties from an object using the delete
keyword.
delete person.isEmployed;
Methods: In JavaScript, objects can also contain functions as values. These functions are called methods of the object.
let person = {
name: "John",
sayHello: function() {
console.log("Hello, my name is " + this.name);
}
};
person.sayHello(); // Output: "Hello, my name is John"
this
keyword refers to the current object instance. It allows methods to access other properties or methods of the same object.Object Constructor: You can also create objects using constructor functions or ES6 classes.
// Constructor function
function Person(name, age) {
this.name = name;
this.age = age;
}
let john = new Person("John", 30);
// ES6 Class
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
let john = new Person("John", 30);
These are the key concepts related to objects in JavaScript. Understanding these concepts is crucial for effectively working with data and creating complex applications in JavaScript.
Arrow functions are a concise way to write anonymous function expressions in JavaScript. They were introduced in ECMAScript 6 (ES6) and provide a more succinct syntax compared to traditional function expressions. Here’s an explanation of arrow functions with details:
Syntax: Arrow functions have a compact syntax compared to regular function expressions. The basic syntax is:
(parameters) => { statements }
If the function has only one parameter and a single statement, the parentheses around the parameter and curly braces around the statement can be omitted:
parameter => expression
this
Binding: One of the most significant differences between arrow functions and traditional functions is how they handle the this
keyword. Arrow functions do not have their own this
context. Instead, they inherit this
from the surrounding code (lexical scoping). This behavior can be very useful in situations where this
might change context in traditional functions, such as when dealing with event handlers or callbacks.arguments
object: Unlike traditional functions, arrow functions do not have their own arguments
object. If you need to access the arguments passed to an arrow function, you can use the rest parameter syntax (...args
) or access the arguments
object from the surrounding scope.new
keyword: Arrow functions cannot be used as constructors and cannot be called with the new
keyword. Attempting to do so will result in a runtime error.Use Cases:
map
, filter
, and reduce
.this
confusion: Arrow functions can be beneficial in situations where you want to preserve the value of this
from the enclosing lexical context.Example:
// Traditional function expression
const traditionalFunction = function(x, y) {
return x + y;
};
// Arrow function
const arrowFunction = (x, y) => x + y;
console.log(traditionalFunction(2, 3)); // Output: 5
console.log(arrowFunction(2, 3)); // Output: 5
In summary, arrow functions provide a concise syntax for writing functions in JavaScript, with lexical this
binding and implicit return. They are particularly useful in scenarios where brevity and clarity are important. However, they may not be suitable for all use cases, especially when you need access to this
or the arguments
object.
Map: The map()
method creates a new array by calling a provided function on every element in the calling array. It does not mutate the original array.
const numbers = [1, 2, 3, 4, 5];
// Doubling each element in the array
const doubledNumbers = numbers.map(num => num * 2);
console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]
const books = [
{ title: 'Harry Potter', author: 'J.K. Rowling', pages: 336 },
{ title: 'The Lord of the Rings', author: 'J.R.R. Tolkien', pages: 1178 },
{ title: 'To Kill a Mockingbird', author: 'Harper Lee', pages: 281 }
];
// Create a new array with book titles
const bookTitles = books.map(book => book.title);
console.log(bookTitles); // Output: ['Harry Potter', 'The Lord of the Rings', 'To Kill a Mockingbird']
In this example, the map()
method iterates through each element of the numbers
array, applies the provided function (which doubles each element), and returns a new array with the modified elements.
Filter: The filter()
method creates a new array with all elements that pass the test implemented by the provided function. It also does not mutate the original array.
const numbers = [1, 2, 3, 4, 5];
// Filtering out odd numbers
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // Output: [2, 4]
const students = [
{ name: 'Alice', age: 22 },
{ name: 'Bob', age: 18 },
{ name: 'Charlie', age: 25 },
{ name: 'David', age: 30 }
];
// Filter students who are older than 20
const olderStudents = students.filter(student => student.age > 20);
console.log(olderStudents); // Output: [{ name: 'Alice', age: 22 }, { name: 'Charlie', age: 25 }, { name: 'David', age: 30 }]
Here, the filter()
method iterates through each element of the numbers
array, applies the provided function (which checks if the number is even), and returns a new array containing only the elements that pass the test.
Reduce: The reduce()
method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value. It can be used to perform any kind of operation on an array and return a single value.
const numbers = [1, 2, 3, 4, 5];
// Summing up all elements in the array
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // Output: 15
const orders = [
{ id: 1, product: 'Laptop', price: 1000 },
{ id: 2, product: 'Smartphone', price: 500 },
{ id: 3, product: 'Tablet', price: 300 }
];
// Calculate total revenue from orders
const totalRevenue = orders.reduce((total, order) => total + order.price, 0);
console.log(totalRevenue); // Output: 1800
In this example, the reduce()
method takes a function with two parameters: an accumulator (which stores the accumulated result) and the current value being processed. It starts with an initial value of 0 (specified as the second argument), then adds each element of the array to the accumulator, returning the final accumulated value.
Combination of Filter, Map & Reduce :
const transactions = [
{ id: 1, customer: 'Alice', age: 22, amount: 100 },
{ id: 2, customer: 'Bob', age: 25, amount: 200 },
{ id: 3, customer: 'Charlie', age: 30, amount: 150 },
{ id: 4, customer: 'David', age: 28, amount: 300 }
];
// Filter transactions made by customers aged 25 and above
// Map to get the amounts
// Reduce to sum up the total amount
const totalAmountSpentByOlderCustomers = transactions
.filter(transaction => transaction.age >= 25) // Filter
.map(transaction => transaction.amount) // Map
.reduce((total, amount) => total + amount, 0); // Reduce
console.log(totalAmountSpentByOlderCustomers); // Output: 650 (200 + 150 + 300)
In JavaScript, mutability and immutability refer to whether an object’s state can be changed after it’s been created.
Objects: Objects in JavaScript are mutable, meaning their properties can be changed after they’re created.
let obj = { name: 'John', age: 30 };
obj.age = 31; // Mutable
Arrays: Arrays are also mutable in JavaScript.
let arr = [1, 2, 3];
arr.push(4); // Mutable
Primitives: Primitive data types such as strings, numbers, and booleans are immutable.
let str = 'Hello';
str.concat(' World'); // Immutability - 'Hello' remains unchanged
Immutable Libraries: Some libraries and patterns in JavaScript promote immutability, such as using libraries like Immutable.js or functions like Object.freeze()
.
Example with Object.freeze()
:
let obj = Object.freeze({ name: 'John', age: 30 });
obj.age = 31; // This change will not be allowed in strict mode or throw an error in non-strict mode
Example with Immutable.js:
const { Map } = require('immutable');
let map1 = Map({ a: 1, b: 2, c: 3 });
let map2 = map1.set('b', 50); // Returns a new immutable map with the updated value
Destructuring in JavaScript is a convenient way of extracting multiple values from data stored in arrays or objects, and assigning them to variables in a concise manner. Here are two examples demonstrating destructuring:
// Array destructuring
const numbers = [1, 2, 3, 4, 5];
// Destructuring assignment
const [first, second, ...rest] = numbers;
// Using the extracted values
console.log(first); // Output: 1
console.log(second); // Output: 2
console.log(rest); // Output: [3, 4, 5]
In this example, an array numbers
is destructured into variables first
, second
, and rest
. The first two elements of the array are assigned to first
and second
, while the rest of the elements are captured in the rest
variable using the rest syntax (...
).
// Object destructuring
const person = {
name: 'John Doe',
age: 30,
gender: 'male',
country: 'USA'
};
// Destructuring assignment
const { name, age, ...details } = person;
// Using the extracted values
console.log(name); // Output: John Doe
console.log(age); // Output: 30
console.log(details); // Output: { gender: 'male', country: 'USA' }
Here, an object person
is destructured into variables name
, age
, and details
. The name
and age
properties are assigned to corresponding variables, while the remaining properties are captured in the details
object using the rest syntax (...
).
In JavaScript, destructuring assignment can be used not only with arrays and objects but also with other iterable data structures like strings and sets. Here are examples demonstrating destructuring with strings and sets:
// String destructuring
const str = 'hello';
// Destructuring assignment
const [firstChar, secondChar, ...remainingChars] = str;
// Using the extracted values
console.log(firstChar); // Output: h
console.log(secondChar); // Output: e
console.log(remainingChars); // Output: ['l', 'l', 'o']
In this example, a string str
is destructured into individual characters using array destructuring.
// Set destructuring
const mySet = new Set([1, 2, 3, 4, 5]);
// Destructuring assignment
const [firstElement, secondElement, ...restElements] = mySet;
// Using the extracted values
console.log(firstElement); // Output: 1
console.log(secondElement); // Output: 2
console.log(restElements); // Output: [3, 4, 5]
Here, a Set
named mySet
is destructured into individual elements using array destructuring. Sets are iterables, so they can be destructured just like arrays.
So, in JavaScript, while arrays and objects are the most commonly used data structures for destructuring, you can also destructure strings, sets, and any other iterable data structures.