Value vs Reference Types In Javascript

Javascript differentiates Data Types on :
- Primitive Types (Number, String, Boolean, null & undefined).
- Complex Types (Objeccts & Arrays).
Copying Primitive Values :
When copying primitive values, Javascript is going to behave as we expect it to. We just need to see what was the value of the variable at the time of the assignment.
Copying Numbers:
let x = 10;
let y = x;
x = 2;
console.log(x); // 2
console.log(y); // 1
Copying Strings :
let name = "John";
let copiedName = name;
name = "Peter";
console.log(name); // John
console.log(copiedName); // Peter
- As you can see the value of
y&copiedNamedoesn't changed / updated, because they were assigned before updating the respective original values. - It means
xwas assigned toywhen it's value was1&namewas assigned tocopiedNamewhen it's value wasJohn. - Since,
Primitive Types / Valuesare referred to asPass-By-Value, they justremember / storethe value that was assigned to them at the time ofinitialization, & later if theoriginal value(x,name) gets updated, this doesn't affect thenew values(y,copiedName) because they are notsubscribedto original values`.
Copying Complex Values :
When copying complex values, Javascript engine is not going to behave as you initially think it would.
Copying Arrays :
const games = [ 'cricket', 'football' ];
const copiedGames= games;
games.push('tennis');
console.log(games); // [ 'cricket', 'football', 'tennis' ]
console.log(copiedGames); // [ 'cricket', 'football', 'tennis' ]
- As you can see the
games&copiedGamesreturns thesame array, but in the case ofprimitive valueswe got the different output. - Lets try with
Objects.
Copying Objects :
const person = {
firstName : "John",
lastName : "Cena"
}
const newPerson = person;
// Change the firstName
person.firstName("Jane");
console.log(preson); // { firstName : "Jane", lastName : "Cena" }
console.log(newPerson); // { firstName : "Jane", lastName : "Cena" }
- Again, we got the same
object valuesin-case ofcopmlex types. - So, lets see what's happenning...
When a variable is assigned a
primitive value, it just copies that value. We saw that withnumberandstringsexamples.On the other hand, when a variable is assigned a
non-primitive value(such as an object, an array or a function), it is given areferenceto that object’s location inmemory. What does that mean?
In this example above, the variable newPerson doesn’t actually contain the value { firstName: 'John', lastName: 'Cena' }, instead it points to a location in memory where that value is stored.
const person = {
firstName : "John",
lastName : "Cena"
}; // memory-location :- bca154
const newPerson = person; // memory-location :- bca154
- Since, the
Complex Types / Valuesare referred to asPass-By-Reference, When a reference type value is copied to another variable, likenewPersonin the example above, the object is copied by reference instead of value. In simple terms,person&newPersondon’t have their own copy of the value. They point to the same location in memory, for ex:memory-location :- bca154.
// Change the firstName
person.firstName = "Jane";
console.log(preson); // { firstName : "Jane", lastName : "Cena" }
console.log(newPerson); // { firstName : "Jane", lastName : "Cena" }
When a new item is pushed to
person, the array in memory is modified, and as a result the variablenewPersonalso reflects that change.We're never actually making a copy of a
personobject. We're just make a variable that points to the same location in the memory.
Equality
- Since the two variables are returning the same value, lets check by creating two variables with same values & check their
equality.
const personOne = {name : "John"}; // memory-location :- bca112
const personTwo = {name: "John"};
console.log(personOne === personTwo); // memory-location :- bca155
- Here, both the variables
personOne&personTwohave the same values, lets check what we get!
console.log(personOne === personTwo); // false
// since bca112 !== bca155
- You might thought that
equalityof these variablespersonOne&personTwologstrue, but that isn't true. The reason behind that is that although person & otherPerson contain identical objects, they still point to two distinct objects stored in different locations in memory. - Now, let's create a copy of the person object by copying the object itself, rather than creating a completely new instance of it.
const anotherPerson = personOne;
console.log(anotherPerson === personOne); // true
personOne&anotherPersonhold reference to the same location in memory & are therefore considered to be equal.Awesome! We just learned that primitive values are copied by value, and that objects are copied by reference.
- But, how to make a real copy of an object & remove it's
reference. That will allow us to copy an object and change it without being afraid that we'll change both objects at the same time.
Shallow Cloning :
Cloning Arrays :
- There are 2 ways to
shallow-clone / copyan array.
- Spread Operator
- array.slice()
Spread Operator
- Lets create an array of numbers & copy the original array without it's
reference.
const numbers = [ 1, 2, 3];
const copiedNumbers = [ ...numbers ];
// this is how we add `spread opertor` in an array
console.log(numbers); // [1, 2, 3]
console.log(copiedNumbers); // [1, 2, 3 ]
- Now lets try to
updatethe original array(numbers) & log both the arrays to see if thecopiedNumbersarray alsoupdated. Let us also check theequalitybetween them.
numbers.push(4,5);
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(copiedNumbers); // [1, 2, 3 ]
console.log(numbers === copiedNumbers); // false
- Now we get different
outputs, since their reference isdifferent. It means we have successfully copied theoriginal arraywithout it's actualreference. - Hence, change in any of the arrays doesn't reflect to both the arrays.
array.slice()
const numbers = [ 1, 2, 3];
const copiedNumbers = numbers.slice();
// slice() returns shallow copy of some portion of array based upon the arguments passed to it.
numbers.push(4,5);
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(copiedNumbers); // [1, 2, 3 ]
Cloning Objects :
- There are 2 ways to
shallow-clone / copyan object.
- Spread Operator
- Object.assign()
Spread Operator
- Lets create an
person object& copy the originalobjectwithout it'sreference.
const person = {
name: 'Jon',
age: 20,
};
const otherPerson = { ...person };
otherPerson.age = 21;
console.log(person); // {name : "Jon", age : 20 }
console.log(otherPerson); // {name : "Jon", age : 21 }
Object.assign() :
const value= { a: 2 };
const copiedValue= Object.assign({}, value);
// Object.assign() works same as the spread operator.
Deep Cloning :
- Let's try creating a copy of that object, by adding
nested obectto it.
const person = {
firstName: 'Emma',
car: {
brand: 'BMW',
color: 'blue',
wheels: 4,
}
};
const copiedPerson = { ...person };
person.firstName = "Watson";
console.log(person.firstName);
console.log(copiedPerson.firstName);
- Cool, as always we both the objects retun distinct values.
- Now lets try to change the value of the
nestedobject (car) & see what that logs.
person.car.color = "red";
console.log(person.car.color);
console.log(copiedPerson.car.color);
- Oops, We've got the same color
redin both the objects(person&copiedPerson). This is because thespread operatorjust copies thefirst levelof the object. That's why this method namedshallow cloning. - So, to remove
referencefrom the nested object, we have to again performspread operationon thenested object(car). If there aren-number ofnested objects, then we have to performspread operationto all thosenested objectsas-well. This isTrickyright!! - So, to avoid that level of difficulty, we have
Deep Cloning. Deep Cloningcan be achieved by using2methods.
- JSON.stringify()
JSON.parse()
Lets apply this in our previous
personobject & change thebrandthis time.
const person = {
firstName: 'Emma',
car: {
brand: 'BMW',
color: 'blue',
wheels: 4,
}
};
const stringifiedObject = JSON.parse(JSON.stringify(person));
person.car.brand = "AUDI";
console.log(person.car.brand); // "AUDI"
console.log(stringifiedObject.car.brand); // "BMW"
- Hence, Now we get two different values of
brandin nested object. Thus,Deep Cloningishelpful&easierforremoving-reference-from-reference-types.Conclusion :
- For the objects with
one-level-nesting,spread operatorwill be okay, but for theobjectswith more than one level nestingDeep Cloningwill be efficient for destroying all the references.
--> If you like this blog, feel free to like, comment & share with your friends.
--> If there is any thing to be corrected, plz mention in the comment section below, I would appreciate that.




