Understanding JavaScript Mutability

Greg Thompson
4 min readAug 23, 2020

--

In today’s world of computer science and programming, we often work with large datasets in projects. Accidentally modifying data is easy to do and hard to notice without a careful eye. This is why it is important to understand the concept of mutability and how to avoid carelessly editing data that is not meant to be changed. Here, we’ll look at a handful of different methods and how they transform (or don’t) the data they are interacting with.

Mutable vs. Immutable Data

Immutable data cannot be changed, and is comprised of all simple datatypes (i.e. numbers, booleans, and strings). The number 10, for example, will always be the number 10. It is one more than 9 and half of 20. We can perform operations on the number 10, like adding five or squaring, and find different numbers through those operations, but the number 10 remains unchanged. Likewise, the boolean value true will always be true. True simply cannot be false.

Mutable data, on the other hand, can be changed. Mutable datatypes include objects and arrays. These data storage containers would be useless if we could not add values to them or modify them in other ways. Numerous array and object methods that allow data manipulation data are available. It is important to know how those work. We’ll look at some of the trickier ones below.

Mutability in Disguise

Rules surrounding mutability often rear their ugly heads when you least expect. Let’s dig in to an example of a method that appears to mutate data but does not.

On first glance, it seems that the .toUpperCase() method breaks Javascript’s basic rules of mutability, as strings are immutable and their values cannot be changed. However, closer inspection of our str variable shows that its value has actually not been changed. Rather, the .toUpperCase() method returns a new, entirely different string than our original, with its own location in storage, and str is left untouched.

Dangers of Mutation

In mathematics, great beauty can be found when examining graphs. You might recall the concept of reflections in graphs from your high school geometry class. Reflecting any point across the line y = x (a straight line at a 45° angle) is a simple feat — the x and y coordinates of both points will be “swapped.” Reflecting the point A (10, 3) across the line y = x gives us the point A’ (3, 10). Luckily, we have JavaScript’s .reverse() method that models this concept almost flawlessly. Let’s explore the .reverse() method, create some reflections in graphs, and talk more about mutability.

The plotPoint function above takes in an array and plots a point on a graph at x = coordinate[0] and y = coordinate[1]. Currently, this function will produce the following graph:

If we want to “swap” the x and y coordinates of the first point to graph the reflected point, we can use the .reverse() method, like so:

This will successfully graph point b at (1, 3). So, what exactly is the problem? If we wanted to graph both points instead of just point b using the plotPoint function, our graph would look like this:

The reason for this (double) mix-up is that JavaScript’s .reverse() method mutates the original array that it is called on. Although we are not reassigning the variable a, the .reverse() method mutates, or changes, the contents of a anyway. Our variable b has a value of [1, 3] as planned, but a now has that value, too.

How can this mutation be prevented when we want to reverse an array, but keep the original data intact? Enter a wonderful little method, .slice(), that creates a shallow copy of the original array without mutating it. Furthermore, changes to the copied array’s values will not update the original in any way. With the help of the .slice() method, we can modify our code to successfully plot two points that are reflected across the line y =x.

We now have this beautiful graph with two perfectly reflected points and have successfully avoided the dangers of mutation.

Conclusion

It can be difficult to keep track of every JavaScript method and recall which methods mutate data. Understanding how to access and interact with values without mutating data will help make you a more efficient programmer. Even developing a basic grasp of how mutability in JavaScript works can set off a warning bell when your code is not working as expected.

--

--