Mutability
Mutability refers to the ability of a value or data structure to be changed after it has been created.
Primitive values are immutable
Primitive values (string
, number
, bigint
, boolean
, undefined
, symbol
and null
) are immutable, which means that they cannot be changed once created.
let myString = "Hello, world!"
// Attempting to mutate (change) the string:
myString[0] = "J"
// -> 'J'
// Proof that strings are immutable, because it didn't change:
myString
// -> 'Hello, world!'
The string "Hello, world!"
will always be "Hello, world!"
.
We can change the value to which the variable is grasping (a new string that also will be immutable), but the string itself (the value) will remain the same (immutable):
let myString = "Hello, world!"
myString
// -> 'Hello, world!'
myString = "Hey, world!"
myString
// -> 'Hey, world!'
myString[0] = "X"
// -> 'X'
myString
// -> 'Hey, world!'
Objects are mutable
Objects are mutable, as they can be modified:
// Object creation
const person = {
name: 'Sarah',
age: 30
};
// Change the value of a property
person.age = 42;
// Add a new property
person.gender = 'Female';
// Delete a property
delete person.age;
person;
// -> {
// "name": "Sarah",
// "gender": "Female"
// }
In this scenario, an object is mutable because we can change its properties.
If the object properties are other objects, their values will be mutable, whereas if they are primitive values, their values will be immutable.
person.gender[0] = "X"
person
// -> {
// "name": "Sarah",
// "gender": "Female"
// }
Even though an object is mutable, its properties might not be.
We can make an object immutable by using the Object.freeze()
function:
// Object creation
const person = {
name: 'Sarah',
age: 30
};
Object.freeze(person)
person.name = "Connor"
person.enemy = "T-1000"
person
// -> {
// {
// "name": "Sarah",
// "age": 30
// }
The reference confusion in objects
When we assign a primitive value to a variable, we are making that variable point to a primitive value in the memory of the machine. We can then assign the variable to another variable, thus making the second variable grasp the first one, and, by extension, reference the same value.
If we wanted to change the value of the second variable, ss we cannot change primitive values (they are immutable), we could assign a new value. By doing so, the second variable will be referencing a new value.
let variable1 = "hello"
let variable2 = variable1
variable2 === variable1
// -> true
variable2 = "bye"
variable2 === variable1
// -> false
variable1
// -> 'hello'
variable2
// -> 'bye'
With objects, the behaviour is a bit different. We can assign an object to a variable, which means that the variable grasps the object, or has a reference to it. If we then assign that variable to another variable, the new variable will grasp the first one and, by extension, reference the same object. As objects are mutable, a change in the object will affect both variables.
const object1 = {
value1: "abc",
value2: 123
}
const object2 = object1
object2 === object1
// -> true
object2.value1 = "xyz"
object1
// -> {
// "value1": "xyz",
// "value2": 123
// }
object2
// -> {
// "value1": "xyz",
// "value2": 123
// }
On the other hand, we can define a new object in the second variable, and thus make it not reference the same object as the first one. One thing to note is that, even if all the object properties are the same, these two objects will be different:
const object1 = {
value1: "abc",
value2: 123
}
const object2 = {
value1: "abc",
value2: 123
}
object2 === object1
// -> false
object2.value1 = "xyz"
object1
// -> {
// "value1": "abc",
// "value2": 123
// }
object2
// -> {
// "value1": "xyz",
// "value2": 123
// }
References
Thanks for reading, and see you next time! ๐
๐๏ธ NEWSLETTER - If you want to hear about my latest articles and interesting software development content, subscribe to my newsletter.
๐ฆ TWITTER - Follow me on Twitter.