In this article, we'll learn what shallow and deep copying is, and the best way to deep copy an object in JavaScript.
Shallow Copying vs Deep Copying
In a reassignment operation involving primitive data types such as strings, numbers and booleans, the original variable is copied by JavaScript.
For example, consider the following code:
let x = 3;
y = x; // x is copied into y
y++; // y is incremented
console.log(y); // now 4
console.log(x); // still 3
In this case, the value 3 is copied into y and then x is disconnected from y. So mutating y does not affect x.
Conversely, with non-primitive data types like arrays and objects, only a reference to the values is passed. So when the copy is mutated, the original also gets mutated. This is also known as shallow copying.
let adam = { name: 'Adam' };
let jason = adam;
jason.name = 'Jason';
console.log(adam.name); // outputs "Jason"
console.log(jason.name); // outputs "Jason"
If we instead want to copy an object so that we can modify it without affecting the original object, we need to make a deep copy.
5 Ways To Deep Copy Objects in JavaScript.
In JavaScript, we can perform a copy on objects using the following methods:
Method | Pros | Cons |
---|---|---|
shallow copy with = | clear and direct, the default | only shallow copies objects |
JSON.stringify() and JSON.parse() | deep copies nested objects | doesn't copy functions |
Object.assign() | copies the immediate members of an object—including functions | doesn't deep copy nested objects |
the ... spread operator | simple syntax, the preferred way to copy an objects | doesn't deep copy nested objects |
Lodash cloneDeep() | clones nested objects including functions | adds an external dependency to your project |
Conclusion
As you've seen, there are a number of ways to copy a variable in JavaScript. None of them is perfect for every occasion, so you'll have to be careful to chose the best method for each situation.