# Level Up Your JavaScript: A Practical Guide to Array Manipulation

Arrays are one of the most important data structures in JavaScript. But knowing how to *store* data is only half the battle, but what to do with the array and data stored in it? How can the array be manipulated? This is where array methods come into play. These are the built in functions provided by the JavaScript.

## Mutating vs Non-Mutating

The array methods are of two types, Mutating and Non-Mutating. They have certain behavior when called upon an array:

| Type | What it means | Methods |
| --- | --- | --- |
| **Mutating** | Changes the original array directly | `push`, `pop`, `shift`, `unshift` |
| **Non-Mutating** | Returns a NEW array and the original is untouched | `map`, `filter`, `reduce`, `forEach` |

```javascript
// Mutating = original array changes
const playlist = ["Starboy", "Blinding Lights"];
playlist.push("As It Was");
console.log(playlist); // ["Starboy", "Blinding Lights", "As It Was"]
// Original was changed

// Non-mutating = original array is safe
const scores = [10, 20, 30];
const doubled = scores.map(n => n * 2);
console.log(scores);  // [10, 20, 30]  | untouched
console.log(doubled); // [20, 40, 60]  | brand new array
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">It is adviced to avoid changing data in an array. Prefer non-mutating patterns whenever possible.</div>
</div>

* * *

## Understanding the Callback Function

`map()`, `filter()`, `forEach()`, and `reduce()` accept a **callback** which is a function you provide that gets called on each element. That callback receives up to **3 arguments**:

```javascript
array.map((element, index, array) => {
//          ↑          ↑       ↑
//       the item   position  the full array 
});
```

You only need to declare the ones you'll use:

```javascript
const playlist = ["Starboy", "Blinding Lights", "Flowers"];

// Just the element
playlist.forEach(playlist => console.log(playlist));

// Element + index 
playlist.forEach((playlist, index) => {
  console.log(`${index + 1}. ${playlist}`);
});
// 1. Starboy
// 2. Blinding Lights
// 3. Flowers
```

* * *

## Array Methods

### `push()` and `pop()`

`push()`: *Add to the end.*

`push()` adds one or more elements to the **end** of an array and returns the **new length**.

```javascript
// BEFORE
const playlist = ["Starboy", "Blinding Lights"];
console.log(playlist); // ["Starboy", "Blinding Lights"]

const newLength = playlist.push("As It Was");

// AFTER
console.log(playlist);    // ["Starboy", "Blinding Lights", "As It Was"]
console.log(newLength);   // 3  ← returns new length, not the array itself
```

You can push multiple items at once:

```javascript
const playlist = ["Starboy"];
playlist.push("Blinding Lights", "As It Was", "Lucid Dreams");
console.log(playlist);
// ["Starboy", "Blinding Lights", "As It Was", "Lucid Dreams"]
```

*Real example:* user builds their playlist:

```javascript
const myPlaylist = [];

myPlaylist.push("Blinding Lights");
myPlaylist.push("As It Was");
myPlaylist.push("Starboy");

console.log(myPlaylist);
// ["Blinding Lights", "As It Was", "Starboy"]
console.log(`${myPlaylist.length} songs in your playlist`);
// 3 songs in your playlist
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Another way to push elements into the array can be through spread operators <code>[...arr]</code>. Spread operator push elements into the array without mutating it.</div>
</div>

```javascript

const playlist = ["Starboy", "Blinding Lights"];
// Instead of playlist.push("Flowers")
const newPlaylist = [...playlist, "Flowers"]; 

console.log(playlist);    // ["Starboy", "Blinding Lights"] (Safe!)
console.log(newPlaylist); // ["Starboy", "Blinding Lights", "Flowers"]
```

`pop()`: *Remove from the end*

`pop()` removes the **last element** and **returns** that removed element.

```javascript
// BEFORE
const playlist = ["Starboy", "Blinding Lights", "As It Was"];
console.log(playlist); // ["Starboy", "Blinding Lights", "As It Was"]

const removed = playlist.pop();

// AFTER
console.log(playlist); // ["Starboy", "Blinding Lights"]
// the song that was removed
console.log(removed);  // "As It Was"  
```

Real example: remove the last song you added:

```javascript
const playlist = ["Blinding Lights", "Starboy", "Lucid Dreams"];

function undoLastAdd() {
  const removed = playlist.pop();
  console.log(`Removed: ${removed}`);
  console.log(`Playlist now has ${playlist.length} songs`);
}

undoLastAdd(); // Removed: Lucid Dreams | Playlist now has 2 songs
undoLastAdd(); // Removed: Starboy      | Playlist now has 1 song
```

* * *

### `shift()` and `unshift()`

These work just like `push`/`pop` but operate on the **beginning** of the array.

`shift()`: *Remove from the beginning*

```javascript
// BEFORE
const queue = ["Blinding Lights", "As It Was", "Starboy"];
console.log(queue); // ["Blinding Lights", "As It Was", "Starboy"]

// ACTION
const nowPlaying = queue.shift();

// AFTER
console.log(queue);      // ["As It Was", "Starboy"]
//  song that started playing
console.log(nowPlaying); // "Blinding Lights"  
```

Real example: playing songs in order from a queue:

```javascript
const queue = ["Blinding Lights", "As It Was", "Starboy", "Lucid Dreams"];

function playNext() {
  const song = queue.shift();
  console.log(`Now playing: ${song}`);
  console.log(`Up next: ${queue[0]}`);
  console.log(`${queue.length} songs remaining`);
}

playNext();
// Now playing: Blinding Lights
// Up next: As It Was
// 3 songs remaining

playNext();
// Now playing: As It Was
// Up next: Starboy
// 2 songs remaining
```

`unshift()`: *Add to the beginning*

```javascript
// BEFORE
const queue = ["As It Was", "Starboy"];
console.log(queue); // ["As It Was", "Starboy"]

const newLength = queue.unshift("Blinding Lights");

// AFTER
console.log(queue);     // ["Blinding Lights", "As It Was", "Starboy"]
console.log(newLength); // 3
```

Real example: someone requests a song to play next:

```javascript
const queue = ["Starboy", "Lucid Dreams", "In The End"];

function playNext(song) {
  queue.unshift(song);
  console.log(`"${song}" added to the front`);
  console.log(`Queue: ${queue.join(", ")}`);
}

playNext("Blinding Lights");
// "Blinding Lights" added to the front
// Queue: Blinding Lights, Starboy, Lucid Dreams, In The End
```

You can unshift multiple songs at once and they are inserted in order:

```javascript
const queue = ["Starboy"];
queue.unshift("Song A", "Song B");
console.log(queue); // ["Song A", "Song B", "Starboy"]
```

`push/pop` **vs** `shift/unshift`

![](https://cdn.hashnode.com/uploads/covers/678b775e773554ab7117f20a/2e21f628-f77d-493c-a4ae-7a4de8dad9c5.png align="center")

```plaintext
Think of it like a queue at a concert: - New people join at the back (push). People are let in from the front (shift).
```

| Method | Where | Action | Returns |
| --- | --- | --- | --- |
| `push(item)` | End | Adds item | New length |
| `pop()` | End | Removes item | Removed item |
| `unshift(item)` | Beginning | Adds item | New length |
| `shift()` | Beginning | Removes item | Removed item |

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><code>push</code>/<code>pop</code> are faster than <code>shift</code>/<code>unshift</code> on large arrays. When you add or remove from the beginning, JavaScript has to reindex every element. For performance-sensitive code, prefer <code>push</code>/<code>pop</code> when the order doesn't matter.</div>
</div>

* * *

### `map()`: Transform Every Element

`map()` goes through every item, runs your function on it, and returns a **new array** with the results. The original is never touched.

**How map() works:**

![](https://cdn.hashnode.com/uploads/covers/678b775e773554ab7117f20a/7ed9c937-81f4-4b93-94ab-103bac379dbb.png align="center")

**Syntax:**

```javascript
// Traditional function
const newArray = original.map(function(element) {
  return /* new value */;
});

// Arrow function (preferred)
const newArray = original.map(element => /* new value */);

// With index
const newArray = original.map((element, index) => /* new value */);
```

***Examples***

```javascript
// Double every number
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);

console.log(numbers); // [1, 2, 3, 4, 5]   // unchanged
console.log(doubled); // [2, 4, 6, 8, 10]  // new array

// Add a track number to every song
const playlist = ["Blinding Lights", "As It Was", "Starboy"];
const numbered = playlist.map((song, index) => `${index + 1}. ${song}`);

console.log(playlist); // ["Blinding Lights", "As It Was", "Starboy"]  // unchanged
console.log(numbered); // ["1. Blinding Lights", "2. As It Was", "3. Starboy"]

// Convert all song names to uppercase
const songs = ["blinding lights", "as it was", "starboy"];
const uppercased = songs.map(song => song.toUpperCase());

console.log(uppercased); // ["BLINDING LIGHTS", "AS IT WAS", "STARBOY"]

// Extract just the song title from an array of objects
const tracks = [
  { title: "Blinding Lights", artist: "The Weeknd", plays: 4200 },
  { title: "As It Was",       artist: "Harry Styles", plays: 3800 },
  { title: "Starboy",         artist: "The Weeknd", plays: 5100 }
];

const titles = tracks.map(track => track.title);
console.log(titles); // ["Blinding Lights", "As It Was", "Starboy"]Traditional for loop vs map()
```

`for loop` **vs** `map()`

```javascript
const prices = [10, 25, 50, 100];

// for loop
const discounted = [];
for (let i = 0; i < prices.length; i++) {
  discounted.push(prices[i] * 0.9);
}
console.log(discounted); // [9, 22.5, 45, 90]

// map
const discounted2 = prices.map(price => price * 0.9);
console.log(discounted2); // [9, 22.5, 45, 90]
```

**Named callbacks for complex logic**

```javascript
// For simple transforms, inline is fine
const doubled = numbers.map(n => n * 2);

// For complex logic, extract a named function
function formatProduct(product) {
  return {
    id: product.id,
    label: `${product.name} — $${product.price.toFixed(2)}`,
    inStock: product.quantity > 0
  };
}

const formatted = products.map(formatProduct);
// Cleaner, testable, and shows up by name in stack traces
```

* * *

### `filter()`: Keep Only What You Need

`filter()` goes through every item and keeps only the ones where your function returns `true`. It returns a **new array** which is shorter than or equal to the original. The original is never changed.

**How filter() works**

![](https://cdn.hashnode.com/uploads/covers/678b775e773554ab7117f20a/d5e490e6-7b13-44ef-92a4-30d4ba3f890d.png align="center")

**Syntax**

```javascript
const newArray = original.filter(element => /* true = keep, false = remove */);
```

Examples

```javascript
// Keep only scores above the passing mark
const scores = [4200, 980, 5100, 750, 3800];
const highScores = scores.filter(score => score > 1000);

console.log(scores);     // [4200, 980, 5100, 750, 3800]  
console.log(highScores); // [4200, 5100, 3800]

// Keep only songs with more than 1000 plays
const tracks = [
  { title: "Blinding Lights", plays: 4200 },
  { title: "Heat Waves",      plays: 980  },
  { title: "Starboy",         plays: 5100 },
  { title: "Stay",            plays: 750  },
  { title: "As It Was",       plays: 3800 }
];

const popular = tracks.filter(track => track.plays > 1000);
console.log(popular.map(t => t.title));
// ["Blinding Lights", "Starboy", "As It Was"]

// Keep only songs by a specific artist
const tracks = [
  { title: "Blinding Lights", artist: "The Weeknd" },
  { title: "As It Was",       artist: "Harry Styles" },
  { title: "Starboy",         artist: "The Weeknd" },
  { title: "Watermelon Sugar", artist: "Harry Styles" }
];

const weekndSongs = tracks.filter(track => track.artist === "The Weeknd");
console.log(weekndSongs.map(t => t.title));
// ["Blinding Lights", "Starboy"]
```

`for loop` **vs** `filter()`

```javascript
const scores = [4200, 980, 5100, 750, 3800];

// for loop
const highScores = [];
for (let i = 0; i < scores.length; i++) {
  if (scores[i] > 1000) {
    highScores.push(scores[i]);
  }
}
console.log(highScores); // [4200, 5100, 3800]

// filter()
const highScores2 = scores.filter(score => score > 1000);
console.log(highScores2); // [4200, 5100, 3800]
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><code>filter()</code> is the preferred method for search functionality and filtering a product list by price, category, or a search term typed by the user.</div>
</div>

* * *

### `reduce()`: Combine Everything Into One Value

`reduce()` loops through every element and **accumulates** them into a single result which can be a number, string, object, or another array.

**How reduce() works**

![](https://cdn.hashnode.com/uploads/covers/678b775e773554ab7117f20a/f5f1ba7e-d7b3-4408-b5e7-32bc4b790353.png align="center")

**Syntax**

```javascript
const result = array.reduce((accumulator, currentValue) => {
  return /* updated accumulator */;
}, initialValue); 
```

Step by step functioning:

```javascript
const plays = [4200, 980, 5100, 750, 3800];

const total = plays.reduce((acc, count) => {
  console.log(`acc: ${acc}  +  count: ${count}  =  ${acc + count}`);
  return acc + count;
}, 0);

// acc: 0     +  count: 4200  =  4200
// acc: 4200  +  count: 980   =  5180
// acc: 5180  +  count: 5100  =  10280
// acc: 10280 +  count: 750   =  11030
// acc: 11030 +  count: 3800  =  14830

console.log("Total plays:", total); // Total plays: 14830
```

Practical examples

```javascript
// Total play count across your playlist
const plays = [4200, 980, 5100, 750, 3800];
const totalPlays = plays.reduce((acc, count) => acc + count, 0);
console.log(totalPlays); // 14830

// Total listening hours across all users
const userHours = [1200, 850, 2100, 630, 1750];
const totalHours = userHours.reduce((acc, hours) => acc + hours, 0);
console.log(totalHours); // 6530
console.log("Average:", totalHours / userHours.length); // Average: 1306

// Total cost of a merchandise order
const cart = [
  { item: "Hoodie",  price: 45 },
  { item: "T-Shirt", price: 25 },
  { item: "Cap",     price: 20 }
];

const orderTotal = cart.reduce((acc, product) => acc + product.price, 0);
console.log(`Order total: $${orderTotal}`); // Order total: $90
```

`for loop` **vs** `reduce()`

```javascript
const plays = [4200, 980, 5100, 750, 3800];

// for loop
let total = 0;
for (let i = 0; i < plays.length; i++) {
  total += plays[i];
}
console.log(total); // 14830

// reduce()
const total2 = plays.reduce((acc, count) => acc + count, 0);
console.log(total2); // 14830

// change initial value to notice the changes. remove it, then accumulator initial value becomes the first element. 
// it can also return array and objects
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">It is a good practice to always provide the initial value in reduce method.</div>
</div>

* * *

### `forEach()`: Loop Without a New Array

`forEach()` calls a function on **every element** and **returns nothing**. Use it when you want to *do something* with each element (log it, send it, update the DOM) without needing a result back.

**Syntax**

```javascript
array.forEach((element, index) => {
  // do something — no need to return
});
```

Examples

```javascript
// Print every song in the playlist
const playlist = ["Blinding Lights", "As It Was", "Starboy"];

playlist.forEach(song => {
  console.log(`Now playing: ${song}`);
});
// Now playing: Blinding Lights
// Now playing: As It Was
// Now playing: Starboy

// Print songs with their track number
const playlist = ["Blinding Lights", "As It Was", "Starboy"];

playlist.forEach((song, index) => {
  console.log(`Track ${index + 1}: ${song}`);
});
// Track 1: Blinding Lights
// Track 2: As It Was
// Track 3: Starboy

// Log every user's listening hours
const users = [
  { name: "Saumya", hours: 1200 },
  { name: "Alex",   hours: 850  },
  { name: "Jordan", hours: 2100 }
];

users.forEach(user => {
  console.log(`${user.name} listened for ${user.hours} hours`);
});
// Saumya listened for 1200 hours
// Alex listened for 850 hours
// Jordan listened for 2100 hours
```

`for loop` **vs** `forEach()`

```javascript
const playlist = ["Blinding Lights", "As It Was", "Starboy"];

// for loop
for (let i = 0; i < playlist.length; i++) {
  console.log(playlist[i]);
}

// forEach, no index variable needed
playlist.forEach(song => console.log(song));
```

`forEach()` **vs** `map()`

```javascript
const songs = ["blinding lights", "as it was", "starboy"];

// forEach — runs code on each item, returns nothing
const result = songs.forEach(song => song.toUpperCase());
console.log(result); // undefined  
// forEach always returns undefined

// map — transforms each item, returns a new array
const uppercased = songs.map(song => song.toUpperCase());
console.log(uppercased); // ["BLINDING LIGHTS", "AS IT WAS", "STARBOY"]
```

|  | `forEach()` | `map()` |
| --- | --- | --- |
| Returns | `undefined` | New array |
| Chainable? | No (But can be present at the end of the chain) | Yes |
| Use for | Side effects (logging, DOM, APIs) | Transforming values |

## Method Chaining

The array methods become intresting to use when chained together. This is a syntax pattern where multiple methods are linked together in a single statement. It improves the readability of code and the flow. We also eliminate the need to create more variables.

```javascript
const tracks = [
  { title: "Blinding Lights", artist: "The Weeknd",    plays: 4200 },
  { title: "Heat Waves",      artist: "Glass Animals", plays: 980  },
  { title: "Starboy",         artist: "The Weeknd",    plays: 5100 },
  { title: "Stay",            artist: "The Kid LAROI", plays: 750  },
  { title: "As It Was",       artist: "Harry Styles",  plays: 3800 }
];

// Goal: get the titles of all songs with more than 1000 plays

// Without chaining 
const popular = tracks.filter(track => track.plays > 1000);
const titles  = popular.map(track => track.title);
console.log(titles);
// ["Blinding Lights", "Starboy", "As It Was"]

// With chaining 
const titlesChained = tracks
  .filter(track => track.plays > 1000)
  .map(track => track.title);

console.log(titlesChained);
// ["Blinding Lights", "Starboy", "As It Was"]
```

### Mental Walkthrough:

```plaintext
Need to ADD or REMOVE items?
  ├── End of array   : push() / pop()
  └── Start of array : unshift() / shift()

Need a new array?
  ├── Same length (transformed) : map()
  └── Shorter (filtered)        : filter()

Need a single value from the array?
  └── reduce()

Just need to loop (no new array)?
  └── forEach()
```

| Method | Mutates? | Returns | Use for |
| --- | --- | --- | --- |
| `push(item)` | Yes | New length | Add to end |
| `pop()` | Yes | Removed item | Remove from end |
| `unshift(item)` | Yes | New length | Add to beginning |
| `shift()` | Yes | Removed item | Remove from beginning |
| `map(fn)` | No | New array, same length | Transform each item |
| `filter(fn)` | No | New array, equal or shorter | Select items by condition |
| `reduce(fn, init)` | No | Single value | Aggregate / combine |
| `forEach(fn)` | No | `undefined` | Side effects |

* * *

## References

*   [MDN: Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
    
*   [MDN: push()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push)
    
*   [MDN: pop()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop)
    
*   [MDN: shift()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift)
    
*   [MDN: unshift()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift)
    
*   [MDN:](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) [map](http://Array.prototype.map)[()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
    
*   [MDN: filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
    
*   [MDN: reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
    
*   [MDN: forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
