JavaScript array methods 1/3 - altering arrays
Tags: javascript, webdev, beginners, tutorial
Published: 2021-08-15 19:06:11

The Array prototype in modern JavaScript contains many useful methods which every developer should know. However, some of them were introduced in the more recent ECMAScript. So if you don't keep up with the newest standards or you're just a beginner - it is a good time to learn something new. I'm also going to show you some tricks and trivia about these methods.

-----

### Before you read
If you're an absolute beginner before reading this article you can check my [brief introduction to JavaScript arrays](https://blog.danieo.me/a-brief-introduction-to-javascript-arrays/) where I discussed this construct in short.

## How to add new items to an array?
**push()**! One of the most common operations that we can do on arrays. It simply adds new elements to the array.

```javascript
const array = ["🐒", "🐬", "🐅"];
array.push("🐓");
console.dir(array) // Output: ["🐒", "🐬", "🐅", "🐓"]
```

**push()** will automatically extend the size of the array and add our new element at the end. We can **push()** more than one element at once:

```javascript
const array = ["🐒", "🐬", "🐅"];
array.push("🐓", "🐉", "🐄");
console.dir(array) // Output: ["🐒", "🐬", "🐅", "🐓", "🐉", "🐄"]
```

It's also worth noting that **push()** returns the new length of the array.

```javascript
const array = ["🐒", "🐬", "🐅"];
console.dir(array.push("🐉")); // Output: 4
console.dir(array); // Output: ["🐒", "🐬", "🐅", "🐉"]
```

Sometimes we may need to manually extend an array and add elements at certain indexes.

```javascript
const array = [];
array[2] = "🐬";
console.dir(array); // Output: [undefined, undefined, "🐬"]
array[0] = "🐅";
array[1] = "🐉";
console.dir(array); // Output: ["🐅", "🐉", "🐬"]
```

In this example, we create an empty array. The next line extends its size to n+1 and adds 🐬 as the last value.

> Thanks to the console.dir() in the third line you can see that there are some undefined values in this array. [As I said in my brief introduction to JavaScript arrays](https://blog.danieo.me/a-brief-introduction-to-javascript-arrays/), when you're extending the length of an array, JavaScript creates new elements with undefined values to meet the new size.

This method also works on existing arrays:

```javascript
const array = ["🐅", "🐬"];
array[4] = "🐄";
console.dir(array); // Output: ["🐅", "🐬", undefined, undefined, "🐄"]
```

## How to concat/merge arrays?

One of the possibilities is to use **concat()**:

```javascript
const array1 = ["🐒", "🐬", "🐅"];
const array2 = ["🐓", "🐉"];
const result = array1.concat(array2);
console.dir(result); // Output: ["🐒", "🐬", "🐅", "🐓", "🐉"]
```

It merges two or more arrays and returns the new array. Here's an example on three arrays:

```javascript
const array1 = ["🐒", "🐬", "🐅"];
const array2 = ["🐓", "🐉"];
const array3 = ["🐎", "🐄"];
const result  = array1.concat(array2, array3);
console.dir(result); // Output: ["🐒", "🐬", "🐅", "🐓", "🐉", "🐎", "🐄"]
```

But what if I want to merge one array INTO another array without the need to assign a third variable? ES2015 introduced a so-called destructuring assignment which in combination with **push()** can do it!

```javascript
const array1 = ["🐒", "🐬", "🐅"];
const array2 = ["🐓", "🐉"];
array1.push(...array2);
console.dir(array1); // Output: ["🐒", "🐬", "🐅", "🐓", "🐉"]
```

Ta dam! Now we have all of the elements of the second array in our first array.

Using destructuring we can achieve a similar behavior to **concat()**. We just need to destruct the merged arrays into another array.

```javascript
const array1 = ["🐒", "🐬", "🐅"];
const array2 = ["🐓", "🐉"];
const array3 = ["🐎", "🐄"];
const result = [...array1, ...array2, ...array3];
console.dir(result);
```

## Removing elements from the array

### How to remove the last element from the array?

It's as simple as calling the **pop()** function on the array.

```javascript
const array = ["🐅", "🐬", "🐄"];
array.pop();
console.dir(array); // Output: ["🐅", "🐬"]
```

**pop()** has also a useful property because it returns the removed element!

```javascript
const array = ["🐅", "🐬", "🐄"];
const lastElement = array.pop();
console.dir(lastElement); // Output: "🐄"
```

### How to remove the first element from the array?

Here in handy comes **shift()**. Similar to **pop()** it also returns the element being removed.

```javascript
const array = ["🐅", "🐬", "🐄"];
const firstElement = array.shift();
console.dir(firstElement); // Output: "🐅"
console.dir(array); // Output: ["🐬", "🐄"]
```

### How to remove elements from the array on a specific index?

To remove a specific element we can use the **delete** operator.

```javascript
const array = ["🐅", "🐬", "🐄"];
delete array[1];
console.dir(array); // Output: ["🐅", undefined, "🐄"]
```

It removes the element completely - the array now does not have an element with index 1. The interesting part of this is the fact, that we are still left with an array with a length of 3. If you want to leave the element and don't want it to have value just set it to _undefined_. Example:

```javascript
const array = ["🐅", "🐬", "🐄"];
delete array[1];
console.dir(array.length); // Output: 3
console.dir(1 in array); // Output: false
console.dir(array); // Output: ["🐅", undefined, "🐄"]

array[1] = '🐬';
array[1] = undefined;
console.dir(array.length); // Output: 3
console.dir(1 in array); // Output: true
console.dir(array); // Output: ["🐅", undefined, "🐄"]
```

But what when we want to remove the element AND shorten the array? For this case, we can use **splice()**.

```javascript
const array = ["🐅", "🐬", "🐄"];
array.splice(1, 1);
console.dir(array); // Output: ["🐅", "🐄"]
```

The first argument of **splice()** is the _startIndex_, it sets the place where we want to start "cutting" our array. The second argument determines the length of the "cut". In 0ut case we only want to delete "🐬" so we just start "cutting" on index 1 and we want to remove just one element. Here is another example of removing more elements.

```javascript
const array = ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"];
array.splice(2, 3);
console.dir(array); // Output: ["🐅", "🐬", "🐉"]
```

Now our "cut" has started on "🐄" and we wanted to remove three elements starting from that place.

With splice, we can also fill the gap of the removed elements by passing more arguments.

```javascript
const array = ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"];
array.splice(2, 2, "🐖", "🦙");
console.dir(array); // Output: ["🐅", "🐬", "🐖", "🦙", "🐓", "🐉"]
```

or using destructuring, we can fill the gap with another array.

```javascript
const array = ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"];
const fillArray = ["🐖", "🦙"];
array.splice(2, 2, ...fillArray);
console.dir(array); // Output: ["🐅", "🐬", "🐖", "🦙", "🐓", "🐉"]
```

Now let's compare all three methods and see the results!

```javascript
const array = ["🐅", "🐬", "🐄"];
delete array[1];
console.dir(array.length); // Output: 3
console.dir(1 in array); // Output: false
console.dir(array); // Output: ["🐅", undefined, "🐄"]

array[1] = "🐬";
array[1] = undefined;
console.dir(array.length); // Output: 3
console.dir(1 in array); // Output: true
console.dir(array); // Output: ["🐅", undefined, "🐄"]

array[1] = "🐬";
array.splice(1,1);
console.dir(array.length); // Output: 2
console.dir(1 in array); // Output: true
console.dir(array); // Output: ["🐅", "🐄"]
```

Reassuming: 

* **delete** removes the element but does not affect the array's size.
* setting an element to _undefined_ does not remove it completely nor affects the array's size.
* **splice()** removes the element and affects the array's size.

## Creating a string from an array - joining all elements into one string

Sometimes we need to create one string from all of the elements of the array, we can do it by using **join()**.

```javascript
const array = ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"];
const result = array.join();
console.dir(result); // Output: "🐅,🐬,🐄,🐒,🐓,🐉"
```

We can also specify the separator by passing it as the first argument.

```javascript
const array = ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"];
const result = array.join(' | ');
console.dir(result); // Output: "🐅 | 🐬 | 🐄 | 🐒 | 🐓 | 🐉"
```

## Creating an array from a string - splitting strings

We can achieve this by calling **split()** on our string. I know that **split()** is not a part of the Array prototype, but I thought that I should mention it when I'm talking about its counterpart - **join()**.

```javascript
const string = "🐅,🐬,🐄,🐒,🐓,🐉";
const result = string.split();
console.dir(result); // Output: ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"]
```

The default separator for split() is "," but we can change it to whatever we want.

```javascript
const string = "🐅|🐬|🐄|🐒|🐓|🐉";
const result = string.split("|");
console.dir(result); // Output: ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"]
```

## How to reverse an array?

JavaScript also has a method for this - and (how surprising...) it's named... **reverse()**.

```javascript
const array = ["🐅", "🐬", "🐄"];
const result = array.reverse();
console.dir(result); // Output: ["🐄", "🐬", "🐅"]
```

But there is one problem with this method. It's mutating our original array. Well, it is only a problem if you want to preserve the original array.

```javascript
const array = ["🐅", "🐬", "🐄"];
const result = array.reverse();
console.dir(result); // Output: ["🐄", "🐬", "🐅"]
console.dir(array); // Output: ["🐄", "🐬", "🐅"]
```

What can we do to solve this issue? Well... just call concat() or **slice()** without any arguments.

```javascript
const array = ["🐅", "🐬", "🐄"];
const result = array.concat().reverse();
console.dir(result); // Output: ["🐄", "🐬", "🐅"]
console.dir(array); // Output: ["🐅", "🐬", "🐄"]
```

> **NOTE**. This works because **concat()** and **slice()** are returning a copy of the array - not a reference. By using **reverse()** after them we're only altering the copy.

Or (a cleaner solution) using our best friend, the hero we all needed but didn't deserve him, destructuring assignment.

```javascript
const array = ["🐅", "🐬", "🐄"];
const result = [...array].reverse();
console.dir(result); // Output: ["🐄", "🐬", "🐅"]
console.dir(array); // Output: ["🐅", "🐬", "🐄"]
```

> **NOTE**. Here we are just destructuring our array into another array, which is going to be reversed. So it's basically also calling **reverse()** on a copy.

We can also implement our own reverse function (this is only for **absolute geeks**).

Just kidding, we're not going to reinvent the wheel. I mean, you can, but... I'm too busy and we have to cover some more methods. However, [these guys](https://stackoverflow.com/questions/10168034/how-can-i-reverse-an-array-in-javascript-without-using-libraries) have time to do this, and you can check their thread for some funky solutions.

## How to add new elements to the beginning of an array?

If JavaScript methods were people, **push()** and **shift()** would be a couple with a kid named **unshift()**. **unshift()** like **push()** will add new elements to the array but at the beginning.

```javascript
const array = ["🐅", "🐬", "🐄"];
array.unshift("🐉", "🐓");
console.dir(array); // Output: ["🐉", "🐓", "🐅", "🐬", "🐄"]
```

And like **push()** it also accepts more than one element.

```javascript
const array1 = ["🐅", "🐬", "🐄"];
const array2 = ["🐎", "🐄"];
array1.unshift(...array1);
console.dir(array1); // Output: ["🐉", "🐓", "🐅", "🐬", "🐄"]
```

Also, we can use destructuring to merge an array to the beginning of another.

Also similarly to **push()**, **unshift()** returns the new length of the array.

```javascript
const array = ["🐒", "🐬", "🐅"];
console.dir(array.unshift("🐓")); // Output: 4
console.dir(array); // Output: ["🐓", "🐒", "🐬", "🐅"]
```

## How to sort an array in JavaScript?

Sorting in JS is achieved with the **sort()** method. It utilizes an in-place algorithm so it doesn't copy the array, it alters the original.

```javascript
const array = ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"];
array.sort();
console.dir(array); // Output: ["🐄", "🐅", "🐉", "🐒", "🐓", "🐬"]
```

If we want to keep the original we can do the same trick that we have done with **reverse()**.

```javascript
const array = ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"];
const result = array.slice().sort();
console.dir(array); // Output: ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"]
console.dir(result); // Output: ["🐄", "🐅", "🐉", "🐒", "🐓", "🐬"]
```

```javascript
const array = ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"];
const result = [...array].sort();
console.dir(array); // Output: ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"]
console.dir(result); // Output: ["🐄", "🐅", "🐉", "🐒", "🐓", "🐬"]
```

> NOTE. Emojis are just unicode characters and every emoji has it's unique code. For example 🐄 is U+1F404 and 🐉 is U+1F409. The algorithm is going to sort by this codes.

By default, this method sorts the elements using an ascending order - from lower to higher. If we want to sort in descending order we can write our own _compare function_ (more on that in a moment) or just **reverse()** the sorted array (as it's more performant).

```javascript
const array = ["🐅", "🐬", "🐄", "🐒", "🐓", "🐉"];
array.sort().reverse();
console.dir(array); // Output: ["🐬", "🐓", "🐒", "🐉", "🐅", "🐄"]
```

The default behavior of the **sort()** method causes also a very interesting problem, let's try to sort an array consisting of only numbers.

```javascript
const array = [3, 45, 12, 1, 78, 369];
array.sort();
console.dir(array); // Output: [1, 12, 3, 369, 45, 78]
```

It provides us with one conclusion.
![Cat standing in snow, wondering how were these numbers sorted](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r9khxz5at23yhnxj053u.jpg)

This is because by default sort is converting the elements to strings and comparing them in UTF-16. So when comparing words like "water" and "fire", "fire" comes first but when converting numbers to strings like 100 and 5 we end up with "100" coming before "5". To solve this we need to provide our own compare function as the first argument.

```javascript
const array = [3, 45, 12, 1, 78, 369];
array.sort((first, second) => first - second);
console.dir(array); // Output: [1, 3, 12, 45, 78, 369]
```

Ah, much better.

> NOTE. We use `first - second` rather than `first > second` because it's more performant.

![Benchmark result - sort using arithmetics is faster than sort using comparison](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gzf6jiev2dc25a8silmp.png)

The problem with sorting number arrays is not our only concern. If you're French, Polish, German, Czech, Spanish or a citizen of another country whose native language has some letters with diacritics and you want to compare some local strings... well your life is not easy then. Here's hows **sort()** is working with accent letters.

```javascript
const array = ["turkuć podjadek", "konik polny", "komar", "mucha", "ćma"];
array.sort();
console.dir(array); // Output: ["komar", "konik polny", "mucha", "turkuć podjadek", "ćma"]
```

This example is using some Polish insect names. The words with an accent are just put at the end. For example "ćma" should be first but it's last. To fix this we need to provide our own compare function again.

```javascript
const array = ["turkuć podjadek", "konik polny", "komar", "mucha", "ćma"];
array.sort((first, second) => first.localeCompare(second));
console.dir(array); // Output: ["ćma", "komar", "konik polny", "mucha", "turkuć podjadek"]
```

Now it's working. **localeCompare()** checks if the reference string comes after or before the string given.

## How to get first/last/any n elements from an array?

**slice()** is the solution you're looking for. It accepts two arguments, the start index and the end index, both are optional, but when we provide neither of them - nothing happens. Here are some useful snippets.

### Get the first 3 elements of an array

```javascript
const array = ["🐄", "🐅", "🐉", "🐒", "🐓", "🐬"];
const result = array.slice(0, 3);
console.dir(result); // Output: ["🐄", "🐅", "🐉"]
```

### Get the last element of an array

```javascript
const array = ["🐄", "🐅", "🐉", "🐒", "🐓", "🐬"];
const result = array.slice(-1);
console.dir(result); // Output: ["🐬"]
```

### Get the second half of an array

```javascript
const array = ["🐄", "🐅", "🐉", "🐒", "🐓", "🐬"];
const result = array.slice(array.length / 2);
console.dir(result); // Output: ["🐒", "🐓", "🐬"]
```

### Get the first half of an array

```javascript
const array = ["🐄", "🐅", "🐉", "🐒", "🐓", "🐬"];
const result = array.slice(0, array.length / 2);
console.dir(result); // Output: ["🐄", "🐅", "🐉"]
```

### Get elements after the fourth element

```javascript
const array = ["🐄", "🐅", "🐉", "🐒", "🐓", "🐬"];
const result = array.slice(4);
console.dir(result); // Output: ["🐓", "🐬"]
```

### Get a slice of the array

```javascript
const array = ["🐄", "🐅", "🐉", "🐒", "🐓", "🐬"];
const result = array.slice(2, 4);
console.dir(result); // Output: ["🐉", "🐒"]
```

As you can see, **slice()** can do many things.

## How to flatten arrays?

Flattening means reducing the dimensions of an array. For example, if we got a two-dimensional array we can reduce it to only one dimension using **flat()**.

```javascript
const array = [["🐓", "🐄"], ["🐅", "🐒"]];
const result = array.flat();
console.dir(result); // Output: ["🐓", "🐄", "🐅", "🐒"]
```

Flattening doesn't affect the original array. It's copying its values.

By default **flat()** is going to flatten only one dimension. If you need to flatten a three (or more) dimensional array to just one dimension you have to provide the depth argument.

```javascript
const array = [["🐓", "🐄"], ["🐅", ["🐒", "🐒"]]];
const result = array.flat(2);
console.dir(result); // Output: ["🐓", "🐄", "🐅", "🐒", "🐒"]
```

## How to copy elements within an array?

Sometimes you want to copy an element from one position to another. For this, you can use **copyWithin()**. Like **slice()** this method has many possible use cases.

### Copy first two elements to the last two elements

```javascript
const array = ["🐉", "🐒", "🐓", "🐬", "🐄", "🐅"];
array.copyWithin(-2);
console.dir(array); // Output: ["🐉", "🐒", "🐓", "🐬", "🐉", "🐒"]
```

### Replacing one value with another

```javascript
const array = ["🐉", "🐒", "🐓", "🐬", "🐄", "🐅"];
array.copyWithin(2, 0, 1);
console.dir(array); // Output: ["🐉", "🐒", "🐉", "🐬", "🐄", "🐅"]
```

Here we replaced the 🐓 on index 2, with the piece that goes from index 0 to index 1, which is the 🐉. By changing the second argument to 2 we would also affect the 🐬, basically inserting the 🐉 and 🐒 on the positions where 🐓 and 🐬 were.

```javascript
const array = ["🐉", "🐒", "🐓", "🐬", "🐄", "🐅"];
array.copyWithin(2, 0, 2);
console.dir(array); // Output: ["🐉", "🐒", "🐉", "🐒", "🐄", "🐅"]
```

-----

For now - that's all. We've discussed all methods from the Array prototype that are used to alter arrays. This article series is going to be divided into 3 parts, the next part will deal with array iterators and looping through them, and the third would be about searching elements in arrays. If you appreciate my work consider visiting [my blog](https://blog.danieo.me) and signing to my newsletter (I don't spam, you will be noticed only about my newest content :D).