Preventing Arrays from mutating
You can prevent arrays from mutating in two ways:
- Copy your arrays before working on them
- Use array methods that create a new array
Copy your arrays before working on them
These methods mutate an array:
unshift
shift
push
pop
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:
slice
concat
slice
slice
let you copy an array. You can specify which parts you want to copy by providing two arguments:
startIndex
: Position to start copying from. If not provided, start copying from the first item.
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.
- Add
Winston Churchill
and Albert Einstein
to the start of the list.
- Add
Charles Darwin
and Walt Disney
to the end of the list.
- Add
Pablo Picasso
and Ludwig van Beethoven
after Mahatma Gandhi
.
- Remove
Benjamin Franklin
and Thomas Edison
.
- Remove
Napoleon Bonaparte
and Abraham Lincoln
.
- 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