DEV Community

Cover image for Navigating Mutability and Reference Issues in JavaScript
Damian Demasi
Damian Demasi

Posted on

Navigating Mutability and Reference Issues in JavaScript

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!'
Enter fullscreen mode Exit fullscreen mode

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!'
Enter fullscreen mode Exit fullscreen mode

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"
// }
Enter fullscreen mode Exit fullscreen mode

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"
// }
Enter fullscreen mode Exit fullscreen mode

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
// }
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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
// }
Enter fullscreen mode Exit fullscreen mode

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
// }
Enter fullscreen mode Exit fullscreen mode

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.

Buy Me A Coffee

Cover photo by Ivana Cajina on Unsplash

Top comments (0)