So far in the course you've explored a handful of methods that manipulate data. You'll be growing your arsenal of methods further overtime, so you'll want to gain awareness for exactly how you should expect these methods to manipulate the data you give them. To this end, let's analyze which methods will modify existing data and which methods do not. This concept is referred to as mutability.
When you finish this article, you should be able to:
At its face value, mutability is a simple concept. You may be familiar with the word mutation, which refers to an alteration (usually in DNA). Something that is mutable can be changed, while something that is immutable is unchanging and permanent. To illustrate this concept, you'll begin with strings and arrays. You've spent some time with these two data types and by now you recognize that the two types share many similarities. Both have indices, length, and even share common methods like indexOf. However, they differ greatly in their mutability:
let myArr = ["b", "e", "a", "m"];
myArr[0] = "s";
console.log(myArr); // [ 's', 'e', 'a', 'm' ]
let myStr = "beam";
myStr[0] = "s";
console.log(myStr); // 'beam'
The code above shows that you can assign a new element to an index of an array, BUT you cannot assign a new character to an index of a string. In other words, arrays are mutable, but strings are immutable.
An implication of this discovery is that there are some array methods that will modify an existing array but zero methods that will modify an existing string. Methods that manipulate string data typically return a new string and never modify an existing one. A prime example is toUpperCase:
let word = "piñata";
let newWord = word.toUpperCase();
console.log(word); // 'piñata'
console.log(newWord); // 'PIÑATA'
console.log(word === newWord); // false
Above, notice that the toUpperCase method returns a capitalized version of the string, but does not change the original string.
Now let's examine mutating an array using a function.
function mutateFirstTo5(arr) {
arr[0] = 5;
return arr;
}
let arr = [1, 2, 3, 4];
let mutatedArr = mutateFirstTo5(arr);
console.log(mutatedArr); // [5, 2, 3, 4]
console.log(arr); // [5, 2, 3, 4]
console.log(arr === mutatedArr); // true
Above, notice that the mutatedArr returned from mutateFirstTo5 function is the same array passed into the function. Also, the elements of arr changes after it's been passed into the mutateFirstTo5 function.
It's also worth noting that not every array method will mutate. For example, the indexOf method does not mutate an array, it only reads information about the array. As you learn about methods in the future, you'll be certain to note what mutates and what does not.
Now that you have a grasp of mutability, let's take inventory and identify JavaScript's data types as mutable or immutable.
A quick way to remember the above list is to identify that the composite types (the types that can contain multiple values) of array and object are mutable. The remaining "simpler" types of number, string, and boolean are immutable.
Maybe you are having a tough time believing this. Let's debunk a common argument to turn you into a believer. The skeptical programmer may use this as an argument to show that numbers are mutable:
let myNum = 42;
myNum += 8;
console.log(myNum); // 50
Because the myNum variable now contains 50 where it once contained 42, it may seem the number was mutated. But this is not truly the case. Recall that myNum += 8 is shorthand for myNum = myNum + 8. Since the right-hand side of the assignment evaluates first, you are simply taking the new number of 50 and reassigning it to the myNum variable. This reassignment of a variable name is not a mutation of the original number.
let myNum = 42;
myNum = myNum + 8;
console.log(myNum); // 50
In the same way, if you reassign a variable assigned to an array, then you have not mutated the array.
let arr = ['a', 'b', 'c'];
let refArr = arr;
console.log(refArr); // ['a', 'b', 'c']
// reassign, not mutate, refArr
refArr = 5;
console.log(refArr); // 5
// arr still is assigned to ['a', 'b', 'c']
console.log(arr); // ['a', 'b', 'c']