The spread syntax only creates a new object one level deep. In other words, the spread syntax creates a new object with the same properties as an original object, but if any of those properties are objects or arrays, they will be shared between the original object and the new one.
Example #1
The spread syntax creates a shallow copy of the object property ({ array: [10, 20, 30] }
).
const source = {
prop: "Property",
object: { array: [10, 20, 30] },
};
const copy = { ...source };
copy.object.array[0] = 100;
console.log(source);
If you modify the array
property of the object
property in the copy
variable, it will also affect the source
object. This example demonstrated that the spread syntax is not a deep clone.
Example #2
The spread syntax creates a shallow copy of the object property ([10, 20, 30]
).
const source = {
prop: "Property",
object: [10, 20, 30],
};
const copy = { ...source };
copy.object[0] = 100;
console.log(source);
If you modify the object
property in the copy
variable, it will also affect the source
object. This example demonstrated that the spread syntax is not a deep clone.
Solution #1
Use the spread operator. The copy
and source
will not share the same reference to the array property.
const source = {
prop: "Property",
object: { array: [10, 20, 30] },
};
const copy = { ...source, object: { array: [...source.object.array] } };
copy.object.array[0] = 100;
console.log(source);
When you modify the first element of the array
property in the copy
variable, it does not affect the source
object because copy
and source
have separate references to their object properties and separate references to the array
property within those objects. Therefore, changing the value of copy.object.array[0]
to 100 does not alter the source object.
Solution #2
To perform a simple deep clone, you can use methods like JSON.parse(JSON.stringify( object))
.
const source = {
prop: "Property",
object: { array: [10, 20, 30] },
};
const copy = JSON.parse(JSON.stringify(source));
copy.object.array[0] = 100;
console.log(source);
Caveat
JSON.parse(JSON.stringify(object))
works only for simple data types like objects and arrays. It fails to clone functions, dates, custom objects with methods, and other non-serializable objects.
While JSON.parse(JSON.stringify(object))
is a quick and easy way to shallow clone simple objects and arrays, it is not suitable for deep cloning in more complex scenarios.
For further insights into deep copies, read the article ‘Understanding JavaScript: Creating Deep Copies of Objects and Arrays‘.