Saturday, July 27, 2024

Immutable array updates with Array.prototype.with  |  Blog  |  web.dev

Web DevelopmentImmutable array updates with Array.prototype.with  |  Blog  |  web.dev


Browsers recently gained a new interoperable method that you can call on Arrays:
Array.prototype.with().

This article explores how this method works and how to use it to update an array
without mutating the original array.

Intro to Array.prototype.with(index, value)

The Array.prototype.with(index, value) method returns a copy of the array it’s
called on with the index set to the new value you provide.

The following example shows an array of ages. You’d like to create a new copy of
the array while changing the second age from 15 to 16:

const ages = [10, 15, 20, 25];

const newAges = ages.with(1, 16);
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

Breaking down the code:: ages.with(...) returns a copy of the ages variable
without modifying the original array. ages.with(1, …) replaces the second item
(index = 1). ages.with(1, 16) assigns the second item to 16.

This is how you were able to create a new copy of the array with a modification.

This is pretty useful when you want to make sure that the original array remains
unchanged, and this article covers some of the use cases for this. But, for now,
take a look at what would have happened had you used the bracket notation:

const ages = [10, 15, 20, 25];

const newAges = ages;
newAges[1] = 16;
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 16, 20, 25] (Also changed 🙁)

As you can see, the ages variable was also modified in this example. That’s
because when you assign ages = newAges, JavaScript does not copy the array but
rather creates a reference to the other array. So, any change in one will also
affect the other one as they are both pointing to the same array.

Array.prototype.with() and immutability

Immutability is at the heart of many frontend libraries and frameworks, to name
a few: React (and redux), and Vue

Also, other libraries and frameworks don’t necessarily require immutability but
encourage it for better performance: Angular and Lit

So, developers often had to use other methods that returned copies of arrays
which sacrificed code readability:

const ages = [10, 15, 20, 25];

const newAges = ages.map((age, index) => {
    if (index === 1) {
         return 16;
    }
    return age;
});

console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (Remains unchanged)

Here’s an example Codepen of how .with() can be used in React in combination
with useState to immutably update an array of items:

Since the .with() method returns a copy of the array, you can chain multiple
.with() calls or even other array methods. The following example demonstrates
incrementing the second and third ages from the array:

const ages = [10, 15, 20, 25];

const newAges = ages.with(1, ages[1] + 1).with(2, ages[2] + 1)

console.log(newAges); // [10, 16, 21, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

Other new immutable methods

Three other methods recently became interoperable:

These three methods are, according to MDN, the copying version of their
counterparts. These methods can also be used where immutability is expected or
preferred.

In conclusion, immutable updates can be achieved more easily in
JavaScript with one of the four methods presented in this article. Specifically,
the .with() method makes it easier to update a single element of the array
without mutating the original array.

Check out our other content

Check out other tags:

Most Popular Articles