Deep Copy vs Shallow Copy in JavaScript
When you clone an object in JavaScript, you can either create a deep copy or a shallow copy. The difference is that a deep copy, like Lodash's cloneDeep()
function, recursively clones all nested objects.
For example, the Object.assign()
function lets you shallow clone an object.
const obj = { answer: 42 };
// The `Object.assign()` function is a common way to shallow clone an object
const copy = Object.assign({}, obj);
++copy.answer; // 43
obj.answer; // 42, did not change because `copy` is a copy of `obj`
Shallow cloning does not copy nested objects. So if obj
contains an object name
, Object.assign()
will keep a reference to the original copy of name
rather than creating a copy of name
.
const obj = { name: { first: 'Jean-Luc', last: 'Picard' } };
const copy = Object.assign({}, obj);
copy.name.first = 'Johnny';
obj.name.first; // 'Johnny', `name` was **not** cloned
Generally, to deep clone an object, you need a library like Lodash. There is an alternative: serializing the object to JSON using JSON.stringify()
and then parsing it back using JSON.parse()
.
const obj = { name: { first: 'Jean-Luc', last: 'Picard' } };
const copy = JSON.parse(JSON.stringify(obj));
copy.name.first = 'Johnny';
obj.name.first; // 'Jean-Luc'
However, this approach only works well if your object only contains strings, numbers, booleans, objects, and arrays. For example, if your object has a property
date
that is a JavaScript date, the cloned object's date
property will be a string, because that's how JSON.stringify()
serializes dates.
const obj = { date: new Date('2019-06-01') };
const copy = JSON.parse(JSON.stringify(obj));
obj.date instanceof Date; // true
copy.date instanceof Date; // false, `date` is a string