# Array Methods You Must Know

## Array()

```javascript
const threeEmptySeats = Array(undefined);

console.log(threeEmptySeats); // [undefined]
```

*   Stores the arguments inside an array if multiple or non-number
    
*   Creates an array of N empty slots if only N is provided as an argument (where N is a positive integer)
    
*   Gives RangeError if only N is provided as an argument (where N is a negative integer or decimal number)
    

## Array.of()

```javascript
const singlePassenger = Array.of(undefined);

console.log(singlePassenger); // [undefined]
```

Stores the arguments inside an array no matter the data type

## Difference between Array() and Array.of()

*   Array() and Array.of() works same for all data types except Numbers.
    
*   Array() creates empty slots for positive integers and gives a RangeError on negative integers and decimals.
    
*   But Array.of() takes the value and store it in the slot created.
    

> NOT USEFUL FOR ANYTHING BECAUSE I WILL CREATE AN ARRAY USING \[\], AND IT IS OPTIMIZED BY THE ENGINE AS WELL

## Array.from()

```javascript
const trainCode = Array.from("DUST"); 

console.log(trainCode); // ["D", "U", "S", "T"]

console.log(Array.from(3)); // creates an empty array

console.log(Array.from(3.293)); // creates an empty array

console.log(Array.from({id: 1, name: "Jaspreet Sharma", marks: 100})); // creates an empty array

console.log(Array.from([1,2,3,4])); // [1,2,3,4]

console.log(Array.from("[1,2,3,4]")); // ["[", "1", ",", "2", ",", "3", ",", "4", "]"]

console.log(Array.from(null)); // gives TypeError

console.log(Array.from(1,2,4,5)); // gives TypeError because the second argument must be a function
```

*   Array.from() creates an array of characters when provided a string
    
*   Array.from() creates an empty array when provided number, object
    
*   Array.from() gives TypeError when provided null or undefined
    
*   Array.from() assumes function as a second argument
    

> *USEFUL ONLY IN THE CASE OF CREATING AN ARRAY OF CHARACTERS FROM A STRING. BUT IN THAT CASE ALSO, I CAN USE "HELLO".split("") and it will create an array of characters \["H", "E", "L", "L", "O"\] AND .split() METHOD PROVIDES WAY MORE CHOICE OF HOW YOU WANT TO CHOOSE YOUR SPLITTER*

## split()

```javascript
console.log("DUST".split("")); // ["D", "U", "S", "T"]
```

## length

```javascript
const tempTrain = ["A", "B", "C", "D", "E"]; 

console.log(tempTrain.length); // 5

tempTrain.length = 7; 

console.log(tempTrain); // tempTrain = ["A", "B", "C", "D", "E", empty, empty] 

tempTrain.length = 3; 

console.log(tempTrain); // tempTrain = ["A", "B", "C"] 

tempTrain.length = 5;  

console.log(tempTrain); // tempTrain = ["A", "B", "C", empty, empty]
```

*   length method can be used to increase or decrease the length of an array
    
*   If the length of an array is decreased, then the information is lost
    
*   If the length of an array is increased, then new empty slots are generated
    

> USED ONLY FOR FINDING THE LENGTH OF AN ARRAY

## splice()

```javascript
const nums = [1,2,3,4,5]; 

console.log(nums.splice(0, 3)); // [1,2,3]

console.log(nums); // [4,5]

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

console.log(nums2.splice(2,0,100)); // []

console.log(nums2); // [1,2,100,3,4,5]

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

console.log(nums3.splice(2,1,100)); // [3]

console.log(nums3); // [1,2,100,4,5]
```

splice() mutates the array

> I PERSONALLY WOULD NOT USE IT BECAUSE IT DESTROYS THE STRUCTURE OF DATA & THAT LEADS TO CONFUSION AND ERROR AND THAT IS TRUE FOR ALL MUTATING METHODS

## NON-MUTATING METHODS

### concat()

```javascript
const nums4 = [1,2,3,4,5]; 

console.log(nums4.concat(6,7,8,9,10)); // [1,2,3,4,5,6,7,8,9,10] 

console.log(nums4); // [1,2,3,4,5]

console.log(nums4.concat([4,5,6,7,89,5])); // [1,2,3,4,5,4,5,6,7,89,5] 

console.log(nums4); // [1,2,3,4,5]

console.log(nums4.concat([[4,5,6,7,89,5]])); // [1,2,3,4,5,[4,5,6,7,89,5]] 

console.log(nums4); // [1,2,3,4,5]

console.log(nums4.concat({name: "Jaspreet Sharma", age: 21})); // [1,2,3,4,5,{name: "Jaspreet Sharma", age: 21}] 

console.log(nums4); // [1,2,3,4,5]

console.log(nums4.concat(null)); // [1,2,3,4,5,null] 

console.log(nums4); // [1,2,3,4,5]
```

concat() is a non-mutating array method which inserts the arguments it takes at the end of an array and returns a new array without changing the contents of the original array

### slice()

```javascript
console.log(nums4.slice()); // [1,2,3,4,5] 

console.log(nums4); // [1,2,3,4,5]

console.log(nums4.slice(0,3)); // [1,2,3] 

console.log(nums4); // [1,2,3,4,5]

console.log(nums4.slice(0,1,100)); // [1] 

console.log(nums4); // [1,2,3,4,5]
```

*   slice() is a non-mutating alternative of .splice()
    
*   Because it is non-mutating, we cannot insert or delete or change the contents of original array
    
*   But can return part of an array or the entire array
    
*   slice() is used to copy an array, eg: `const copyArr = originalArr.slice();`
    

### flat()

```javascript
const nums5 = [1,2,3,[4,5,6,[7,8,9]], [[[[[10]]]]]]; 

console.log(nums5.flat(Infinity)); // [1,2,3,4,5,6,7,8,9,10] 

console.log(nums5); // [1,2,3,[4,5,6,[7,8,9]], [[[[[10]]]]]]

console.log(nums5.flat()); // [1,2,3,4,5,6,[7,8,9],[[[[10]]]]] 

console.log(nums5); // [1,2,3,[4,5,6,[7,8,9]], [[[[[10]]]]]]
```

flat() is a non-mutating array method which returns a new array containing all the elements and sub-arrays deflated upto default depth of 1 and can deflate upto infinity.

## indexOf()

```javascript
const nums6 = [1,2,3,4,5]; 

console.log(nums6.indexOf(1)); // 0 

console.log(nums6.indexOf(2)); // 1 

console.log(nums6.indexOf(3)); // 2 

console.log(nums6.indexOf(4)); // 3 

console.log(nums6.indexOf(5)); // 4 

console.log(nums6.indexOf(7)); // -1 

console.log(nums6.indexOf(Infinity)); // -1 

console.log(nums6.indexOf("hello")); // -1 

console.log(nums6.indexOf("2")); // -1

const fruits = ["apple", "Banana", "dragon fruit"]; 

console.log(fruits.indexOf("a")); // -1 

console.log(fruits.indexOf("apple")); // 0 

console.log(fruits.indexOf("fruit")); // -1 

console.log(fruits.indexOf("dragon")); // -1 

console.log(fruits.indexOf("banana")); // -1 

console.log(fruits.indexOf("dragon fruit")); // 2
```

*   indexOf() is an array method that takes a searchElement as a first argument and returns the index of the searchElement in the array if existed, otherwise return -1
    
*   searchElement must exactly match the element in the array
    

> Useful to find the index of an element in the array if the complete element is known

## includes()

```javascript
const nums6 = [1,2,3,4,5]; 

console.log(nums6.includes(6)); // false 

console.log(nums6.includes(4)); // true 

console.log(nums6.includes(5)); // true 

console.log(nums6.includes(Infinity)); // false

const fruits = ["apple", "Banana", "dragon fruit"];

console.log(fruits.includes("a")); // false 

console.log(fruits.includes("apple")); // true 

console.log(fruits.includes("banana")); // false 

console.log(fruits.includes("fruit")); // false 

console.log(fruits.includes("dragon fruit")); // true
```

*   includes() is an array method that takes a searchElement as a first argument and returns a boolean value, that is, true if the searchElement exists in an array, otherwise return false
    
*   searchElement must exactly match the element in the array
    

> Useful to find whether the element exists in an array or not, if the complete element is known

## typeof

```javascript
console.log(typeof []); // object 

console.log(typeof null); // object 

console.log(typeof {}); // object
```

Suppose I am getting an input from the user and I used typeof to find the data type of input and it came out to be Object. Now, how would I know whether the input is an array or object or null because all of them have object data type.

## Array.isArray()

```javascript
console.log(Array.isArray([])); // true 

console.log(Array.isArray(null)); // false 

console.log(Array.isArray({})); // false
```

Now, I am sure that the input I am getting is surely an Array, nothing else.

## \[index\]

```javascript
const names = ["Jaspreet Sharma", "Hitesh Sir", "Piyush Sir", "Anirudh Sir"]; 

console.log(names[-1]); // undefined 

console.log(names[4]); // undefined 

console.log(names[2]); // Piyush Sir
```

## at()

```javascript
const names = ["Jaspreet Sharma", "Hitesh Sir", "Piyush Sir", "Anirudh Sir"];

console.log(names.at(-1)); // Anirudh Sir 

console.log(names.at(4)); // undefined 

console.log(names.at(2)); // Piyush Sir
```

*   at() takes an argument of a Number and returns element at that index or undefined
    
*   If the argument passed is the valid index in the array (element is present at that index in the array), then it returns the element present at that index, otherwise return -1
    
*   at() can also takes a negative index and it starts accessing the elements from the end of an array. Eg: `arrayName.at(-1)` will access the last element of the array `arrayName`.
    
*   Accessing out of bounds in an array will return undefined
    

## sort()

```javascript
const nums8 = [5,2,8,48,6,71,5,36,1,5,23,35,8]; 

console.log(nums8.sort((a,b) => a-b)); // array of Numbers -> [1,2,5,5,5,6,8,8,23,35,36,48,71] 

console.log(nums8); // array of Numbers -> [1,2,5,5,5,6,8,8,23,35,36,48,71]
```

sort() is a mutating array method that takes a compareFunction (or callback) as an argument and returns the array in the sorted fashion

## Spread Operator (...)

```javascript
const originalArray = ["hello", 1, "How are you ?", {id: 1, salary: 1000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]]; 

const copiedArray = [...originalArray]; // array -> originalArray gets shallow copied into copiedArray

console.log(originalArray); // array -> ["hello", 1, "How are you ?", {id: 1, salary: 1000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]] 

console.log(copiedArray); // array -> ["hello", 1, "How are you ?", {id: 1, salary: 1000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]]

originalArray[3].salary = 2000; // array -> ["hello", 1, "How are you ?", {id: 1, salary: 2000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]];

console.log(originalArray); // array -> ["hello", 1, "How are you ?", {id: 1, salary: 2000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]]; 

console.log(copiedArray); // array -> ["hello", 1, "How are you ?", {id: 1, salary: 2000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]]
```

*   Spread operator (...) is used to shallow copy an object and array
    
*   Shallow copying means the nested objects and arrays will not be copied or passed by value. Insted they will be passed by reference.
    

## structuredClone()

```javascript
const originalArray2 = ["hello", 1, "How are you ?", {id: 1, salary: 1000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]]; 

const copiedArray2 = structuredClone(originalArray2); // array -> originalArray2 gets deep copied into copiedArray2

console.log(originalArray2); // array -> ["hello", 1, "How are you ?", {id: 1, salary: 1000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]] 

console.log(copiedArray2); // array -> ["hello", 1, "How are you ?", {id: 1, salary: 1000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]]

originalArray2[3].salary = 2000; // array -> ["hello", 1, "How are you ?", {id: 1, salary: 2000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]];

console.log(originalArray2); // array -> ["hello", 1, "How are you ?", {id: 1, salary: 2000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]]; 

console.log(copiedArray2); // array -> ["hello", 1, "How are you ?", {id: 1, salary: 1000}, [1,2,3,4,5], [[1,2], [3,4], [5,6]]]
```

*   structuredClone() is used to deep copy an object and array
    
*   Deep copying means the nested objects and arrays will be copied or passed by value.
    

## Template Literals (conversion into string)

```javascript
const r = `${[1,2,3,4,5]}`; 

console.log(r); // "1,2,3,4,5" 

console.log(typeof r); // "string"
```

## forEach()

```javascript
const orders = [
{ dish: "pasta", price: 14, spicy: true, qty: 2 },
{ dish: "macroni", price: 10, spicy: false, qty: 5 },
{ dish: "noodles", price: 18, spicy: true, qty: 1 },
{ dish: "salad", price: 5, spicy: false, qty: 3 },
{ dish: "momos", price: 20, spicy: true, qty: 1 },
];

const myData = orders.forEach((order,index) => console.log(`${index+1}: ${order.qty} x ${order.dish}`)); // 5 prints in format specified 

console.log(myData); // undefined

console.table(orders); // same
```

*   forEach() method accepts a callback as an argument and returns void (or nothing or undefined)
    
*   callback should accept a data type as a first argument and index of that data type as the second argument
    
*   forEach() iterates over each element of the array
    
*   forEach() is a non-mutating array method
    

```javascript
const orders = [
{ dish: "pasta", price: 14, spicy: true, qty: 2 },
{ dish: "macroni", price: 10, spicy: false, qty: 5 },
{ dish: "noodles", price: 18, spicy: true, qty: 1 },
{ dish: "salad", price: 5, spicy: false, qty: 3 },
{ dish: "momos", price: 20, spicy: true, qty: 1 },
];

orders.forEach(order => { 
    if(order.dish === "noodles") break;
    console.log(order.dish); 
}) // Error: cannot use break here
```

*   forEach() method expects synchronous callback, i.e., forEach loop can neither break nor an iteration can be jumped over using continue
    
*   forEach() method does not wait for promises (async - await)
    

> USEFUL FOR LOGGING SOMETHING OUT OF THE ARRAY OF OBJECTS
> 
> DO NOT HANDLE PROMISES USING forEach() method

## map()

```javascript
const orders = [
{ dish: "pasta", price: 14, spicy: true, qty: 2 },
{ dish: "macroni", price: 10, spicy: false, qty: 5 },
{ dish: "noodles", price: 18, spicy: true, qty: 1 },
{ dish: "salad", price: 5, spicy: false, qty: 3 },
{ dish: "momos", price: 20, spicy: true, qty: 1 },
];

const receiptLines = orders.map(order => `${order.dish}: ${order.qty * order.price}`); // array of strings -> ["pasta: 28", "macroni: 50", "noodles: 18", "salad: 15", "momos: 20"] 

console.log(receiptLines); // ["pasta: 28", "macroni: 50", "noodles: 18", "salad: 15", "momos: 20"]

console.table(orders); // same
```

*   map() accepts a callback as an argument and returns an array
    
*   callback should accept a data type as a first argument
    
*   map() iterates over each element of the array
    
*   map() is a non-mutating array method
    

> USEFUL FOR EXTRACTING AN INFORMATION OUT OF EACH ELEMENT OF AN ARRAY & THEN STORING THAT INFORMATION INSIDE AN ARRAY

## filter()

```javascript
const orders = [
{ dish: "pasta", price: 14, spicy: true, qty: 2 },
{ dish: "macroni", price: 10, spicy: false, qty: 5 },
{ dish: "noodles", price: 18, spicy: true, qty: 1 },
{ dish: "salad", price: 5, spicy: false, qty: 3 },
{ dish: "momos", price: 20, spicy: true, qty: 1 },
];

const spicyOrders = orders.filter(order => order.spicy); // array of objects -> [{ dish: "pasta", price: 14, spicy: true, qty: 2 },{ dish: "noodles", price: 18, spicy: true, qty: 1 },{ dish: "momos", price: 20, spicy: true, qty: 1 },]; 

console.table(spicyOrders); // array of objects -> [{ dish: "pasta", price: 14, spicy: true, qty: 2 },{ dish: "noodles", price: 18, spicy: true, qty: 1 },{ dish: "momos", price: 20, spicy: true, qty: 1 },];

console.table(orders); // same
```

*   filter() accepts a callback as an argument and returns an array of same data types as the method is applied upon
    
*   callback should accept a data type as a first argument
    
*   filter() iterates over each element of the array
    
*   filter() is a non-mutating array method
    

> USEFUL FOR AS THE NAME SUGGESTS FILTERING OUT ELEMENTS IN AN ARRAY BASED ON CERTAIN CONDITION

## reduce()

```javascript
const orders = [
{ dish: "pasta", price: 14, spicy: true, qty: 2 },
{ dish: "macroni", price: 10, spicy: false, qty: 5 },
{ dish: "noodles", price: 18, spicy: true, qty: 1 },
{ dish: "salad", price: 5, spicy: false, qty: 3 },
{ dish: "momos", price: 20, spicy: true, qty: 1 },
];

const totalRevenue = orders.reduce((sum, order) => sum + order.qty * order.price, 0); // Number -> 131 

console.log(totalRevenue); // Number -> 131

console.table(orders); // same
```

*   reduce() accepts a callback as the first argument and an initialValue as second argument and return data type same as that of initial value
    
*   callback should accept a data type as a first argument
    
*   reduce() iterates over each element of the array
    
*   reduce() is a non-mutating array method
    

> USEFUL FOR CALCULATIONS THAT REQUIRES OVERALL ARRAY. EG: SUM, MEAN, ETC.

```javascript
const orders = [
{ dish: "pasta", price: 14, spicy: true, qty: 2 },
{ dish: "macroni", price: 10, spicy: false, qty: 5 },
{ dish: "noodles", price: 18, spicy: true, qty: 1 },
{ dish: "salad", price: 5, spicy: false, qty: 3 },
{ dish: "momos", price: 20, spicy: true, qty: 1 },
];

const grouped = orders.reduce((acc, order) => { 
    const category = order.spicy ? "spicy" : "mild";
    acc[category].push(order.dish);
    return acc;
}, {spicy: [], mild: []}); // object -> {spicy: ["pasta", "noodles", "momos"], mild: ["macroni", "salad"]} 

console.log(grouped); // object -> {spicy: ["pasta", "noodles", "momos"], mild: ["macroni", "salad"]}
```

## Pipelining

### toSorted()

```javascript
const orders = [
{ dish: "pasta", price: 14, spicy: true, qty: 2 },
{ dish: "macroni", price: 10, spicy: false, qty: 5 },
{ dish: "noodles", price: 18, spicy: true, qty: 1 },
{ dish: "salad", price: 5, spicy: false, qty: 3 },
{ dish: "momos", price: 20, spicy: true, qty: 1 },
];

const mildReport = orders 
                   .filter(order => !order.spicy) 
                   .map(order => {return {dish: order.dish, total: order.qty * order.price}})
                   .toSorted((a,b) => a.total-b.total) 
// array of objects -> [{dish: "salad", total: 15}, {dish: "macroni", total: 50}] 

console.log(mildReport); // array of objects -> [{dish: "salad", total: 15}, {dish: "macroni", total: 50}]
```

*   toSorted() is non-mutating alternative of .sort() method.
    
*   It accepts compareFunction() as an argument and returns a sorted array
    
*   toSorted() does not mutate the original array
