Immutable Array Operations - JavaScript

Posted on October 05, 2019

Svelte JS documentation reads:

Because Svelte’s reactivity is triggered by assignments, using array methods like push and splice won’t automatically cause updates. For example, clicking the button doesn’t do anything.

It further goes on to replace the push operation with:

function addNumber(newNum) {
numbers = [...numbers, newNum];
}

calling it the idiomatic way.

Then it says,

You can use similar patterns to replace pop, shift, unshift and splice.

Let’s see.

1. Unshift

This is the polar opposite of the push we saw in Svelte docs.

Adds one or more elements to the beginning of an array and returns the new length of the array.

Simply reverse it:

function addNumber(newNum) {
numbers = [newNum, ...numbers];
}

2. Pop

removes the last element from an array and returns that element. This method changes the length of the array.

First, we have to remove the last element without mutating the array. We know slice returns a copy of the array given start and end indices.

function removeNumber() {
numbers = [...numbers.slice(0, numbers.length - 1)];
}

3. Shift

removes the first element from an array and returns that removed element. This method changes the length of the array.

Remove first element without mutating the array. slice to the rescue again.

function removeNumber() {
numbers = [...numbers.slice(1)];
}

Let’s try out few of other conditions where we can apply the same:

4. Splice

changes the contents of an array by removing or replacing existing elements and/or adding new elements

That’s few things, let’s break them down:

  1. Deletes items starting at an index
function removeNumbers(index, numberOfItems) {
numbers = [
...numbers.slice(0, index),
...numbers.slice(index + numberOfItems),
];
}
  1. Inserts item at given index
function insertNumber(index, newNumber) {
numbers = [...numbers.slice(0, index), newNumber, ...numbers.slice(index)];
}
  1. Inserts items at a given index.

Notice the plural.

function insertNumbers(index, ...rest) {
numbers = [...numbers.slice(0, index), ...rest, ...numbers.slice(index)];
}

Double Bonus 🎉🎉:

Remove item based on a condition:

function removeItem() {
numbers = numbers.filter(num => num > 5);
}

Change all items in the array:

function multiplyArray() {
numbers = numbers.map(num => num * 2);
}

Anything more complicated, Array reduce is your friend.

Happy immutability.