There are a few ways to clone objects in JavaScript. You might know that if you assign an object to a new variable like you can do with a string literal, a number, or other primitives, you won’t end up with a copy of the object, you’ll end up with a pointer to the original object. That’s because with objects, JavaScript passes them by reference. It passes a location in memory to the new object. We can see it in action
const person1 = {
age: 35,
name: 'Jen',
address: '1 Martin Pl, Sydney NSW 2000',
}
const person2 = person1;
console.log(person1);
console.log(person2);
The console log is this:
> {age: 35, name: 'Jen', address: '1 Martin Pl, Sydney NSW 2000'}
> {age: 35, name: 'Jen', address: '1 Martin Pl, Sydney NSW 2000'}
So it kinda looks like we’ve copied an object, but if I change the value of one of the properties on person1, what happens to person2?
person1.name = 'Julie';
console.log(person1);
console.log(person2);
The output is this:
> {age: 35, name: 'Julie', address: '1 Martin Pl, Sydney NSW 2000'}
> {age: 35, name: 'Julie', address: '1 Martin Pl, Sydney NSW 2000'}
The name in both console logs is Julie. That’s because when I assigned person1 to person2, it didn’t make a copy, it just pointed person2 to the original object. Changes to one variable will necessarily change the other.
So if I want a real copy of person1 whose values can change independently, how do I do it?
Cloning Objects
There are a few ways of cloning objects in JavaScript. One longhand way is the for…in loop which you can use to iterate over the properties of an object
const person3 = {}
for (let key in person1)
person3[key] = person1[key]
console.log(person1);
console.log(person3);
The output is:
> {age: 35, name: 'Jen', address: '1 Martin Pl, Sydney NSW 2000'}
> {age: 35, name: 'Jen', address: '1 Martin Pl, Sydney NSW 2000'}
So theoretically I have two separate objects here. Let’s test it:
person3.name = 'Julie';
console.log(person1);
console.log(person3);
> {age: 35, name: 'Jen', address: '1 Martin Pl, Sydney NSW 2000'}
> {age: 35, name: 'Julie', address: '1 Martin Pl, Sydney NSW 2000'}
Great, now we see an object for Jen and an object for Julie!
Using the Object class to clone objects
But there are quicker ways of doing this. One is to use the Object class that is built in to JS. As the Mozilla docs say, nearly all objects in JS are instances of this class, and it’s very handy. I can clone an object using its assign method. From the Mozilla documentation:
Copies the values of all enumerable own properties from one or more source objects to a target object.
So here’s how:
const person4 = Object.assign({},person1);
person4.name = 'Julie';
console.log(person1);
console.log(person4);
> {age: 35, name: 'Jen', address: '1 Martin Pl, Sydney NSW 2000'}
> {age: 35, name: 'Julie', address: '1 Martin Pl, Sydney NSW 2000'}
So here I am passing a new empty object as the first argument and person1 as the second. The assign method is cloning person1 into the new object and pointing the constant person4 at that object.
Using the Spread Operator to clone objects
I quite like the Object.assign method, but some say that an even more elegant way of cloning objects is to use the spread operator. You can use it to do all sorts of cool stuff, but here I’ll just use it to quickly clone an object:
const person5 = { ...person1 };
person5.name = 'Julie';
console.log(person1);
console.log(person5);
> {age: 35, name: 'Jen', address: '1 Martin Pl, Sydney NSW 2000'}
> {age: 35, name: 'Julie', address: '1 Martin Pl, Sydney NSW 2000'}
Oh yeah, ok, it is elegant!
By the way, if you didn’t know it, the address I’ve used for Jen and Julie is actually the General Post Office in Sydney’s Martin Place. You can find out more about it here if you’re interested in that kind of thing.
So what’s next?
There is another layer to cloning objects in JS, and it has to do with how the above 3 methods handle nested objects. You can read all about it in my post Cloning Objects in JavaScript Part 2 – a deeper dive!