Skip to Content

How to Clone Objects in JavaScript: A Complete Guide

Cloning objects, arrays, and other data structures is a common requirement in JavaScript programming. Whether you need to duplicate a simple object, a nested array, or an instance of a class, JavaScript provides several methods to achieve cloning. This guide will cover various techniques to clone anything in JavaScript, discussing shallow and deep cloning methods.

JavaScript shallow and deep clone example

Shallow Cloning

Shallow cloning generates a new object that is a duplicate of the original. However, if the original object contains references to other objects, these references are copied to the new object. As a result, changes to the nested objects will appear in both the original and the cloned objects.

Using the Spread Operator

The spread operator (...) provides a straightforward method for creating a shallow copy of an object:

let original = {a: 1, b: {c: 2}};
let shallow = {...original};

console.log(shallow); // {a: 1, b: {c: 2}}
console.log(shallow.b === original.b); // true

The same can also be done with an array:

let original = [1, 2, { a: 3 }];
let shallow = [...original];

console.log(shallow); // { a: 1, b: {c: 2}}
console.log(shallow.b === original.b); // true

Using Object.assign

Object.assign is another method for shallow cloning objects:

let original = {a: 1, b: {c: 2}};
let shallow = Object.assign({}, original);

console.log(shallow); // {a: 1, b: {c: 2}}
console.log(shallow.b === original.b); // true

Deep Cloning

Deep cloning creates a new object and recursively copies all properties from the original object, including nested objects, ensuring the cloned object is entirely independent of the original.

Using JSON.parse and JSON.stringify

For objects and arrays that can be serialized to JSON, JSON.parse and JSON.stringify provide a simple way to deep clone.

let original = {a: 1, b: {c: 2}};
let clone = JSON.parse(JSON.stringify(original));

console.log(deep); // {a: 1, b: {c: 2}}
console.log(deep.b === original.b); // false

Using a Recursive Function

A custom recursive function can handle deep cloning of more complex structures, including those with non-serializable properties.

function clone(obj) {
if (obj === null || typeof(obj) !== "object") {
return obj;
}

if (Array.isArray(obj)) {
let array_copy = [];

for (let i = 0; i < obj.length; i++) {
array_copy[i] = clone(obj[i]);
}

return array_copy;
}

let obj_copy = {};

for (let key in obj) {
if (obj.hasOwnProperty(key)) {
obj_copy[key] = clone(obj[key]);
}
}

return obj_copy;
}

let original = {a: 1, b: {c: 2}};
let clone = clone(original);

console.log(clone); // {a: 1, b: {c: 2}}
console.log(clone.b === original.b); // false

Using structuredClone

The structuredClone method is a more modern approach and provides a way to deep clone objects, including those with complex data types such as Date and Map.

let original = {a: 1, b: {c: 2}};
let clone = structuredClone(original);

console.log(clone); // {a: 1, b: {c: 2}}
console.log(clone.b === original.b); // false

Cloning Special Data Types

Cloning Dates

Dates can be cloned using the new Date constructor.

let original = new Date();
let clone = new Date(original.getTime());

console.log(clone); // Cloned Date object
console.log(clone === original); // false

Cloning Sets

Sets can be cloned using their respective constructors.

let original = new Set([1, 2, 3]);
let clone = new Set(original);

console.log(clone); // Cloned Set
console.log(clone === original); // false

Cloning Maps

Maps can also be cloned using their respective constructors.

let original = new Map([[1, "a"], [2, "b"]]);
let clone = new Map(original);

console.log(clone); // Cloned Map
console.log(clone === original); // false

Conclusion

Cloning objects in JavaScript can be simple or complex, depending on the structure and data types. Understanding when to use shallow versus deep cloning is crucial for preventing unintended side effects and ensuring data integrity.

Created: May 19, 2024