Beware!!!! JavaScripts Object are Mutable

Published Mar 05, 2018Last updated Mar 06, 2018

Perhaps you are a newbie to programming or maybe an unwitting dude from another programing language and now dabbling into JavaScript (or simply JS). Then you should be wary of the potential bugs that can ensue from the misapply of some concepts in JS; Object Mutation is one of such.

What is Mutability?

Mutability simply means "liability or tendency to change"; anything that is capable of changing its context is said to be mutable. Murphy's law warns that "things will go wrong in any given situation, if you give them a chance." So bringing this to Javascript simply means a variable/constant assigned to hold a bunch of key-value pairs can be mistakenly changed in the course of a computation.

Before I explain further Let me explain some core concepts,
variables values can be re-assigned to other variables in two ways:

  1. Pass By value: When a parameter is passed by value, the initial holder(variable) and the latter variable will become two independent variables with the same value. If any of the variables goes ahead to modifies its parameter values, the effect is not visible to the to the other. for example.

const variable1 = 20;

let variable2 = variable1;

variable2 = variable2 + 10;



console.log(variable1)

//20

console.log(variable2)

//30

From the example above, It can be observed that even though variable2 was initially assigned the exact value of variable1 when varible2 was changed, It had no effect on Variable1. This simply means that the two variables are pointing at different memory space in the computer even though one is an exact copy of the other

2.Pass By reference: On the other hand, when a parameter is passed by reference, the initial holder(variable) and the later variable are exactly the same for they still point at the same memory space in the computer. A change/mutation in one will result in a simultaneous change in the other. This is the case for a JavaScript object. e.g


const mondayDiet = {

mainDish: "rice",

dessert: "fish",

appetizer: "cake",

drink: "milk",

}



let tuesdayDiet = mondayDiet;



//now let change a few things in Tuesday diet assuming we want to eat chicken for //dessert and Tuesday and want to also drink soda instead of milk



tuesdayDiet.dessert = "chicken";

tuesdayDiet.drink = "soda";



console.log(mondayDiet)

//{

// mainDish: "rice",

// dessert: "chicken",

// appetizer: "cake",

// drink: "soda",

//}



console.log(tuesdayDiet)

//{

// mainDish: "rice",

// dessert: "chicken",

// appetizer: "cake",

// drink: "soda",

//}



From the above example, it can be observed that the intention was to create Tuesday diet by assigning it to Monday's diet (since they have common main dish and appetizer) and modifying it to show the slight differences,
but what we ended up doing is changing the two days to reflect just Tuesday's diet. As simple as this mistake, it can cause big problems in larger applications if the object mutations are not properly managed and this may result in conditions whereby expected value is not equal to outputted value.

So what do we do now?

There are workaround techniques to create copies of an Object in javascript without mutation of the parent object and to mention a few,

  1. The ES6 spread operator:

const mondayDiet = {

mainDish: "rice",

dessert: "fish",

appetizer: "cake",

drink: "milk",

}



let tuesdayDiet = {...mondayDiet};



tuesdayDiet.dessert = "chicken";

tuesdayDiet.drink = "soda";



console.log(mondayDiet)

//{

// mainDish: "rice",

// dessert: "fish",

// appetizer: "cake",

// drink: "milk",

//}



console.log(tuesdayDiet)

//{

// mainDish: "rice",

// dessert: "chicken",

// appetizer: "cake",

// drink: "soda",

//}



  1. The ES6 Object.assign method

const mondayDiet = {

mainDish: "rice",

dessert: "fish",

appetizer: "cake",

drink: "milk",

}



let tuesdayDiet = Object.assign({}, mondayDiet);



tuesdayDiet.dessert = "chicken";

tuesdayDiet.drink = "soda";



console.log(mondayDiet)

//{

// mainDish: "rice",

// dessert: "fish",

// appetizer: "cake",

// drink: "milk",

//}



console.log(tuesdayDiet)

//{

// mainDish: "rice",

// dessert: "chicken",

// appetizer: "cake",

// drink: "soda",

//}



There are also external libraries that can be used to achieve the same functionality e.g lodash A much more complex and full-time implementation is the immutable library

Discover and read more posts from Ibrahim Usman
get started