How to Clone an Object in JavaScript
Because objects in JavaScript are passed by reference, when you assign an object to a new variable JavaScript does not duplicate the object. Instead, it creates a duplicate pointer to the same object.
If we edit the value of the object from our new variable, we might not expect the original to change, but it does.
const inventory1 = {"bananas": 4};
const inventory2 = inventory1;
inventory2.apples = 3;
console.log(inventory1);
// {"bananas": 4, "apples": 3};
Attempting to deleting an object for which a pointer has been duplicated will not free up memory. The original pointer will be deleted, but the object will be preserved because the second pointer requires it. This is a form of closure.
One way to avoid mutating an object is to freeze it. All pointers to a frozen object will only be able to reference the original and not change it. However, what if you want to make a true copy an object?
The typical first suggestion is to use the .assign method from the Object. This will clone an object, but it is a shallow clone. This is fine if the source object doesn’t contain a nested object or array:
const inventory1 = {"bananas": 4};
const inventory2 = Object.assign({}, inventory1);
inventory2.apples = 3;
console.log(inventory1);
// {"bananas": 4};
console.log(inventory2);
// {"bananas": 4, "apples": 3};
If the original object contains a nested object, including an array, then you’ll need a different solution. Since .assign only clones the top level of data, a nested object would not be duplicated. Instead, a reference to the nested object is copied, which leaves the source object susceptible to mutation.
The next example illustrates the problem: The nested object spices is mutated by the change to inventory2. Both objects will show the same count of basil because they are pointing to the same data:
const inventory1 = {"bananas": 4, "spices": {"basil": 3}};
const inventory2 = Object.assign({}, inventory1);
inventory2.spices.basil = 5;
console.log(inventory1);
// {"bananas": 4, "spices": {"basil": 5}};
console.log(inventory2);
// {"bananas": 4, "spices": {"basil": 5}};
For a deep clone of an object, use the JSON.stringify method to convert the object to a string, and then use JSON.parse to convert it back into an object. This duplicates the data including all nested objects. A change in one will not affect the other:
const inventory1 = {"bananas": 4, "spices": {"basil": 3}};
const inventory2 = JSON.parse(JSON.stringify(inventory1));
inventory2.spices.basil = 5;
console.log(inventory1);
// {"bananas": 4, "spices": {"basil": 3}};
console.log(inventory2);
// {"bananas": 4, "spices": {"basil": 5}};
Related posts:
Helpful references:
Have feedback on this topic?