The spread operator is a new addition to the set of operators in JavaScript ES6. The spread operator is commonly used to make copies of JS Array /objects. Now, we could also use earlier existing vanilla JS with many inbuilt functions to achieve the same but the new spread operator just makes it simple also avoiding some inherited complexity, which includes shallow and deep cloning etc. I will just explain it in a nutshell:
Array/Object spread operator :
// Assume you have the following object:
const yoda = {
fullName : "Yoda",
species: "Unknown",
jediOrder : "Jedi Master",
affiliation: ["Jedi Order", "Galactic Republic"]
}
console.log(yoda)
/*
{
fullName: 'Yoda',
species: 'Unknown',
jediOrder: 'Jedi Master',
affiliation: [ 'Jedi Order', 'Galactic Republic' ]
}
*/
Now let’s assume you want to create a new object(person) with a different name (AKA - Mace Windu) and species but with the same jediOrder and affiliation. You could do this by specifying only the properties you want and using the spread operator for the rest, like below:
const maceWindu = {
...yoda,
fullName : "Mace Windu",
species: "Human",
}
console.log(maceWindu)
/*
{
fullName: 'Mace Windu',
species: 'Human',
jediOrder: 'Jedi Master',
affiliation: [ 'Jedi Order', 'Galactic Republic' ]
}
*/
What the code above does, is spread over the Yoda object and get all its properties, then overwrite the existing properties with the ones we’re passing. Now, let's make another person but this time with different values for 'name' & 'jediOrder'
const skywalker = {
...maceWindu,
fullName : "Luke Skywalker",
jediOrder : "Jedi Knight",
}
console.log(skywalker)
/*
{
fullName: 'Luke Skywalker',
species: 'Human',
jediOrder: 'Jedi Knight',
affiliation: [ 'Jedi Order', 'Galactic Republic' ]
}
*/
This time let's create a new Human Jedi Master just with a new full name and we can copy the rest from another similar object using the spread operator.
const ploKoon = {...maceWindu, fullName : "Plo Koon"}
console.log(ploKoon)
/*
{
fullName: 'Plo Koon',
species: 'Human',
jediOrder: 'Jedi Master',
affiliation: [ 'Jedi Order', 'Galactic Republic' ]
}
Deep & Shallow copy :
Deep Copy: A deep copy of an object is a copy whose properties do not share the same references (point to the same underlying values) as those of the source object from which the copy was made.
Shallow Copy : A shallow copy of an object is a copy whose properties share the same references (point to the same underlying values) as those of the source object from which the copy was made.
So what is meant by deep copy and shallow copy in JavaScript again please 🙏?
A deep copy means that all of the values of the new variable are copied and disconnected from the original variable.
A shallow copy means that certain (sub-)values are still connected to the original variable. To really understand copying, you have to get into how JavaScript stores values.
Below you can see that the spread operator cannot handle the complexity of nested objects as expected.
// Deep & shallow copy
const car1 = {
model : "7 Sedans",
doors : 4,
details: {
brand: "BMW",
color: "red",
price:"1M"
}
}
const car2 = {
...car1,
}
// Let's make some changes through car2 (the second object)
car2.doors = 2
car2.details.color = "blue"
console.log("Details of car1 object now : ")
console.log(car1)
console.log("\n")
console.log("Details of car2 object now : ")
console.log(car2)
/*
Details of car1 object now :
{
model: '7 Sedans',
doors: 4,
details: { brand: 'BMW', color: 'blue', price: '1M' }
}
Details of car2 object now :
{
model: '7 Sedans',
doors: 2,
details: { brand: 'BMW', color: 'blue', price: '1M' }
}
*/
Let's explain:
For car2 object, model and doors are a deep copy as both of these properties are on level-1 of the nest. But for color property of details sub-object it is a shallow copy.
model: '7 Sedans', doors: 2,
details: { brand: 'BMW', color: 'blue', price: '1M' }
For car1 object,
model: '7 Sedans', doors: 4,
details: { brand: 'BMW', color: 'blue', price: '1M' }
Here color property under the details sub-object is in the level-2 of the nest hence here color property shares the same memory space (references) in both the objects, so changing in one will change in all till the original, as we see in this example by changing car2.details.color = "blue" we also have changed it in car1. This is a shallow copy.
}
Finally: 🥁Please.... So for nested objects, the spread operator provides a deep copy of the first instance (first level of the nest) of the value, but leaves all nested data as shallow copies that share the same space (same references) in memory with the original data. Be aware of this behaviour ⚠ 🌖.