Preventing Arrays from mutating

Hey ,

I'm thrilled to help you learn JavaScript. Unfortunately, you've landed on a page where you cannot access with your current purchase.

Please upgrade (use this link) access this content.

I'm super eager to help you learn more!

Preventing Arrays from mutating

You can prevent arrays from mutating in two ways:

  1. Copy your arrays before working on them
  2. Use array methods that create a new array

Copy your arrays before working on them

These methods mutate an array:

  1. unshift
  2. shift
  3. push
  4. pop
  5. splice

To prevent arrays from mutating, you copy the array with slice. Then, you work on the copied array.

const array = [1, 2, 3]
const copy = array.slice()

copy.push(4)

console.log(array) // [1, 2, 3]
console.log(copy) // [1, 2, 3, 4]

Use methods that create a new array

These array methods create a new array:

  1. slice
  2. concat

slice

slice let you copy an array. You can specify which parts you want to copy by providing two arguments:

  1. startIndex: Position to start copying from. If not provided, start copying from the first item.
  2. endIndex: Position to stop copying at. (Does not include the item at this position). If not provided, copy until the last item.

If you omit both startIndex and endIndex, slice copies the entire array.

const array = [1, 2, 3]
const copy = array.slice()

console.log(copy) // [1, 2, 3]

If you want to create a copy of the array from the second item onwards, you can set startIndex to 1. You can omit endIndex to copy to the last item.

const array = [1, 2, 3]
const copy = array.slice(1)

console.log(copy) // [2, 3]

If you want to copy to the second last item, you can use the array.length - index trick.

// Copies up to (not including) the last item
const array = [1, 2, 3]
const copy = array.slice(0, array.length - 1)

console.log(copy) // [1, 2]

slice is special. You can use negative indexes to indicate endIndex.

  • -1 means the last item
  • -2 means the second last item
  • -3 means the third last item
  • And so on.
// Copies up to (not including) the last item
const array = [1, 2, 3]
const copy = array.slice(0, -1)

console.log(copy) // [1, 2]

Concat

concat lets you combine two arrays together. It creates a new array so no mutation occurs.

const first = [1, 2]
const second = [3, 4]
const combined = first.concat(second)

console.log(first) // [1, 2]
console.log(second) // [3, 4]
console.log(combined) // [1, 2, 3, 4]

How I work with arrays

There are many flavors to arrays in JavaScript. The possible methods you can use to change or create arrays are: unshift, shift, push, pop, splice, concat, slice, destructuring, rest operators, and spread operators.

When should you use which?

Many articles out there dissuade you from methods that mutate arrays (like push and splice). They recommend methods like slice and concat.

As I programmed, I realized my code got more complicated when I forced myself to use slice and concat. It got so much simpler when I started using push and splice.

I wrote an article about how I work with arrays. It’ll help you understand when I use which method.

Exercise

The following exercises require you to use this people array:

const people = [
  'Benjamin Franklin',
  'Thomas Edison',
  'Franklin Roosevelt',
  'Mahatma Gandhi',
  'Napoleon Bonaparte',
  'Abraham Lincoln'
]

Read how I work with arrays. Use the knowledge you learned from the article to do the following. Make sure people does not get mutated.

  1. Add Winston Churchill and Albert Einstein to the start of the list.
  2. Add Charles Darwin and Walt Disney to the end of the list.
  3. Add Pablo Picasso and Ludwig van Beethoven after Mahatma Gandhi.
  4. Remove Benjamin Franklin and Thomas Edison.
  5. Remove Napoleon Bonaparte and Abraham Lincoln.
  6. Remove Mahatma Gandhi.

Answers

Add Winston Churchill and Albert Einstein to the start of the list.

const added = ['Winston Churchill', 'Albert Einstein', ...people]

Add Charles Darwin and Walt Disney to the end of the list.

const added = [...people, 'Charles Darwin', 'Walt Disney']

Add Pablo Picasso and Ludwig van Beethoven after Mahatma Gandhi.

const gandhiIndex = people.findIndex(p => p === 'Mahatma Gandhi')
const copy = people.slice()
copy.splice(gandhiIndex + 1, 0, ...['Pablo Picasso', 'Ludwig van Beethoven'])

console.log(copy) // This is the after adding Picasso and Beethoven

Remove Benjamin Franklin and Thomas Edison.

const [benjamin, thomas, ...others ] = people
console.log(others) // This is the array without Benjamin and Thomas.

Remove Napoleon Bonaparte and Abraham Lincoln.

const removed = people.slice(0, -2)

Remove Mahatma Gandhi.

const gandhiIndex = people.findIndex(p => p === 'Mahatma Gandhi')
const copy = people.slice()
copy.splice(gandhiIndex, 1)

console.log(copy) // This is the array with Mahatma Gandhi removed