# Array and its CRUD using array methods...

# What is an array in JavaScript ?

Array is a list-like data structure in JavaScript which store elements and is represented with a pair of square brackets[ ]. The elements stored in an array may or may not be of same data type.The data type of array is an **object**. Yes! You read it correctly. 
Let us verify if an array is an object.

```
let testArray = [ "foo" , 100, true, {} ]
console.log(typeof(testArray))    // "object"
```

## Let us now learn about how create, read, update, delete (CRUD) is done on arrays below.

# How arrays are created in JavaScript ?

There are various ways in which array can be created. The most common way of creating an array is assigning an array value to variable.
```
let foo = []    //array with no elements
let cities = ["Delhi" , "New York", "London", "Perth"]
```
You can also create an constructor to create an array.
```
let foo = new Array()    //array with no elements
let cities = new Array("Delhi" , "New York", "London", "Perth");
console.log(cities)    // ["Delhi" , "New York", "London", "Perth"]

let numArray = new Array (2, 3, 4);
console.log(numArray)    // [2, 3, 4]

let numArray2 = newArray(2);
console.log(numArray2 )    // [undefined, undefined]    
```
**Note** : In the above example of `numArray2 `, when a number is passed to constructor to create an array, it creates an array with same number of items with value as undefined.

# How to read data from an array ?

The items from the array is retrieve using the position of the element called as **index**. In JavaScript, the index starts from **0** and it increases sequentially as the elements are added to the array.

```
let testArray = [ "foo" , 100, true, {} ]
console.log(testArray)    // [ "foo" , 100, true, {} ]
```

The range of index in `testArray` is from 0 to 3 i.e 0, 1, 2, 3 and the `length` or number of elements in array is said to be 4.
For example, in above `testArray`, the element "foo" is at index 0, 100 is at index 1 ,true at 2 and so on.

```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"]
console.log(fruits[1])    //  "banana"
console.log(fruits[4]    //   "peach"
let len = fruits.length;
console.log(fruits[len - 2]    // "watermelon"

```
The above example shows that the elements are read using the index values of array.The length property can be used to access elements in reverse order.

**What happens if I try to read the element at index equal to or greater than the length of an array?**
It will simply return "undefined". Try this exercise [here.](https://jsfiddle.net/)

### *at()*
*at()* method takes an index value and returns the element present at that index. It is different from the regular accessing of elements using index as in regular method to access elements in reverse order length property is used (as seen in above example) but *at()* method supports negative index which access the elements in reverse order.Check out the example below

```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"];
console.log(fruits.at(-1))    // "peach"
console.log(fruits[-1])    //undefined
```


### Methods to check elements in an array

### *includes()*
*includes()* method returns a `boolean`(true/false) after checking for element in an array. It returns `true` when element is found in an array and returns `false` when element is not found in an array.

```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"]
let resultOne = fruits.includes("mango");
let resultTwo = fruits.includes("grapes");
console.log(resultOne)    // true
console.log(resultTwo)    // false
```

### *indexOf()*
*indexOf()* method returns the index of element after checking for element in an array. It returns `index` when element is found in an array and returns `-1` when element is not found in an array.

```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"]
let resultOne = fruits.indexOf("mango");
let resultTwo = fruits.indexOf("grapes");
console.log(resultOne)    // 0
console.log(resultTwo)    // -1
```

**Note** : The method *includes()* and *indexOf()* both have an second optional parameter to begin search from the passed index. Check out the example below

```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"]
let resultOne = fruits.includes("mango",2);
let resultTwo = fruits.indexOf("banana",2);
console.log(resultOne)    // false
console.log(resultTwo)    // -1
```
As both the methods are beginning to search the element from 2, they are unable to get the element.

### *find()*
*find()* method returns the `value` of `first` element after checking for element in an array that satisfies the testing condition in the function. It returns `undefined` when no condition is satisfied.

```
let scores = [ 66, 94, 35, 74, 100]
const result = scores.find( item => item > 75);
console.log(result)    // 94

```

### *findIndex()*
*findIndex()* method returns the `index` of `first` element after checking for element in an array that satisfies the testing condition in the function. It returns `-1` when no condition is satisfied.

```
let scores = [ 66, 94, 35, 74, 100]
const result = scores.findIndex( item => item > 75);
console.log(result)    // 1

```

# How to update data in an array ?
### *push()*
*push()* method adds one or more element to the `end of an array`. It returns the `new length` of array.
 
```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"]
console.log(fruits.push("grapes"))    // 6 (new length)
console.log(fruits)    // ["mango", "banana", "apple" , "watermelon", "peach", "grapes"]

```

### *unshift()*
*unshift()* method is a bit similar to *push()*. The only difference is *push()* adds one or more element to the `end of an array` while *unshift()* adds one or more element to the `beginning of an array`. It returns the `new length` of array.
 
```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"]
console.log(fruits.unshift("grapes"))    // 6 (new length)
console.log(fruits)    // ["grapes", "mango", "banana", "apple" , "watermelon", "peach"]

```

### *splice()*
*splice()* method is used for both` insertion and deletion` of elements in an array.It `mutates original array`. It receives three arguments `(startIndex,deleteCount,itemsToInsert)` of which deleteCount and itemsToInsert are optional
 
```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"]
fruits.splice(1, 0, "grapes","orange")
console.log(fruits)    // ["mango", "grapes", "orange", "banana", "apple" , "watermelon", "peach"]
fruits.splice(1,2)
console.log(fruits)    // ["mango", "banana", "apple" , "watermelon", "peach"]

```
**Note** : 
- If startIndex is greater than length then it is automatically set to length of array and no deletion will occur. 
- If startIndex is negative then it will traverse from the end of the list,if it is negative infinity then startIndex is set to 0 automatically



# How to delete data from an array ?
### *pop()*
*pop()* method removes an element from the `end of an array`. It returns the `removed` element from array.
 
```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"]
console.log(fruits.pop())    // "peach"
console.log(fruits)    // ["mango", "banana", "apple" , "watermelon"]

```

### *shift()*
*shift()* method is a bit similar to *pop()*. The only difference is *pop()* removes an element from the `end of an array` while *shift()* removes an element from `beginning of an array`. It returns the `removed` element from array.
 
```
let fruits = ["mango", "banana", "apple" , "watermelon", "peach"]
console.log(fruits.shift())    // "mango"
console.log(fruits)    // ["banana", "apple" , "watermelon", "peach"]

```

# How to create copy of data in an existing array ?
### *using spread operator and rest operator*
ES6 has introduced an easy way to copy data from one array to another array using `...`(three dots)
 Spread operator appears to the left side of destructuring syntax.
 
```
let fruits1 = ["mango", "banana", "apple" , "watermelon", "peach"]
let fruits2 = [...fruits1]
console.log(fruits2)    // ["mango", "banana", "apple" , "watermelon", "peach"]

```

### *concat()*
*concat()* method returns a `new array` by combining two or more arrays `without mutating` the original arrays.
 
```
let fruits1 = ["mango", "banana", "apple" , "watermelon", "peach"]
let fruits2 = ["grapes", "kiwi", "jackfruit"]
let fruits3 = ["guava", "orange"]
let allFruits = fruits1.concat(fruits2,fruits2);
console.log(fruits1)    // ["mango", "banana", "apple" , "watermelon", "peach"]
console.log(allFruits )    // ["grapes", "mango", "banana", "apple" , "watermelon", "peach", "grapes", "kiwi", "jackfruit", "guava", "orange"]

```

### *slice()*
*slice()* method returns a `new array` by slicing an arrays `without mutating` the original array.
It accepts two arguments `startIndex,endIndex`. If no arguments are passed then entire original array
is copied.
 
```
let fruits1 = ["mango", "banana", "apple" , "watermelon", "peach"]
console.log(fruits1.slice(1))    // ["banana", "apple" , "watermelon", "peach"]
console.log(fruits1.slice(1,3))    // ["banana", "apple" , "watermelon"]
console.log(fruits1.slice())    // ["mango", "banana", "apple" , "watermelon", "peach"]

```

# Other useful methods

### *reverse()*
*reverse()* method reverses an array by `mutating original array` i.e the first element is swapped by last element and so on.

```
let fruits1 = ["mango", "banana", "apple" , "watermelon", "peach"]
let reverseArray = fruits1.reverse();
console.log(reverseArray )    // ["peach", "watermelon", "apple", "banana", "mango"]
console.log(fruits1)    // ["peach", "watermelon", "apple", "banana", "mango"]

```

### *sort()*
*sort()* method sorts an array by converting the elements into string and then comparing UTF - 16 code values and sort them accordingly. The default sort order is ascending and it `mutates original array`

```
let fruits1 = ["mango", "banana", "apple" , "watermelon", "peach"]
fruits1.sort();
console.log(fruits1)    // [ "apple", "banana", "mango","peach", "watermelon"]

```
Now lets try default sort method by taking an array of numbers.
```
const numbers = [22, 66, 88, 4, 100, 1, 6]
numbers.sort();
console.log(numbers)    // [1, 100, 22, 4, 6, 66, 88]

```
So, the default sort gives us an unexpected output as all elements are converted into string.
The sort method also takes a comparator function which overrides the default function.
For ascending order, check the example below

```
const numbers = [22, 66, 88, 4, 100, 1, 6];

function ascendingOrder(a,b){
   return (a - b)
}
numbers.sort(ascendingOrder);
console.log(numbers)    // [1, 4, 6, 22, 66, 88, 100]

```
For descending order, check the example below

```
const numbers = [22, 66, 88, 4, 100, 1, 6];

function descendingOrder(a,b){
   return (b - a)
}
numbers.sort(descendingOrder);
console.log(numbers)    // [100, 88, 66, 22, 6, 4, 1]

```

# Before We End ..
I hope you have found this article insightful as we have covered majority of the array methods which helped you have more clear idea about JavaScript Arrays. Do practise various examples to build muscle memory and get command over the basics as they say `"Stronger is the foundation,greater are the heights"`.

Let's connect on [LinkedIn](https://www.linkedin.com/in/pratikbagmare) and [Twitter](https://mobile.twitter.com/pratik_bagmare)







