August 08, 2020
No comments
Everything in Javascript is an object except the primitive values. Primitive values are passed by copy and objects by reference.
The primitives above have object equivelants that wrap around the value and those objects have valueOf() method that returns the value.
null and undefined primitive values do not have object equivelants, but null is a typeof Object as a bug. For backwards compatibility it has remained as an object.
These types are the building blocks of the language, so they are very easy store and are stored directly by their value. Think of them as post it notes, you can write any information on them quickly, they are quickly accessible and when you are done, you can discard them.
1let name = "Liam";2let name2 = "Liam";
Primitive values are cheap and easy to deal with, whenever you assign a primitive value to a variable, javascript engine knows exactly how much memory is needed and allocates the needed amount.
In this way, when name changes, name2 remains the same. They refer to different places in memory.
1// afer you reassign name, its old value is garbage collected2name = "Emil";3name // Emil4name2 // Liam56function nameChanger (name2){7name2 = "Matilda";8return name2;9}1011name2 // Liam12nameChanger(name2) // Matilda13name2 // Liam
The nameChanger function takes in a copy of the name2 variable, Liam, and then inside in its own scope, it has its own name variable that has the value of Liam. Let us see step by step
1nameChanger("Liam")2// step by step what is happening3function nameChanger (name2){4// name === "Liam"5name2 = "Matilda"; // "Liam" value garbage collected,6// name2 in this scope is "Matilda"7return name2;8}
Objects on the other hand act differently as they are treated differently by the engine. Object, Arrays, Functions are complex structures. You can edit them, expand them, delete properties on them.
1let user = {2name: "Emil",3age:23,4admin: false5}67user.name = "Liam"89console.log(user)10{11name: "Liam",12age:23,13admin: false14}
A new object is not created but the object is modified.
When dealing with complex data, instead of copying the whole data (data objects could be gigabytes), language engines usually pass a reference to the memory address of the object.
Think of primitive values being a name on a post-it, and objects being a house. You do not want to move and copy the house each time someone asks, you want to give them the address. Javascript engines passes the reference to the object, it writes the address on a post-it, instead of creating the whole building again.
1const mate0 = {2name: "Liam",3age: 20,4occupation: "student"5}6const mate1 = {7name: "Emil",8age: 25,9occupation: "Developer"10}11const house = {12price: 1_000_000,13bedrooms: 3,14sqm: 140,15housemates:[]16}17function addToHouse(array, house){18house.housemates = house.housemates.concat(array)19}2021addToHouse([mate0, mate1], house)22console.log(house);23mate1.occupation = "bartender";24console.log(mate1)25//{name: "Liam", age: 20, occupation: "bartender"}262728console.log("after change: ", house)29// {price: 1000000, bedrooms: 3, sqm: 140, housemates: Array(2)}30// housemates: Array(2)31// 0: {name: "Liam", age: 20, occupation: "bartender"}32// 1: {name: "Emil", age: 25, occupation: "Developer"}3334house.housemates[1].name = 'Jack';35console.log(mate1) // Jack
After we run the addToHouse, with our house object and array of housemates, we mutated (programming term for change) the actual house object and added the housemates.
Afterwards when we mutated mate0’s occupation, the change was also reflected and when we mutated housemates[1].name through the house object, we changed mate2’s name to Jack.
So the objects in global scope and inside house.housemates array, both refer to the same memory locations. You can change them from both references. This might not always be desired, so you need to be careful.
That is why libraries like loadash have utilitiy functions for deep copying.
If we use object assign to copy the house object, it will create a shallow copy and we will still not have the desirable effect.
Written by Emil Martinov who lives Rotterdam || Istanbul and loves everything js. He tweets mostly about js.