What are the different ways to copy an object or an array?
TL;DR
Use spread syntax or Object.assign() for a shallow copy. Use structuredClone() for values supported by the structured clone algorithm, including nested arrays and objects, cycles, Map, Set, and many built-in types. A JSON stringify/parse round trip is only a lossy conversion for JSON-shaped data, not a general deep-clone algorithm. A library or domain-specific copy routine may be needed for custom classes and semantics.
// Shallow copy of an arrayconst originalArray = [1, 2, 3];const shallowCopyArray = [...originalArray];console.log(shallowCopyArray); // [1, 2, 3]// Shallow copy of an objectconst originalObject = { a: 1, b: 2 };const shallowCopyObject = { ...originalObject };console.log(shallowCopyObject); // { a: 1, b: 2 }// Deep copy using JSON methodsconst deepCopyObject = JSON.parse(JSON.stringify(originalObject));console.log(deepCopyObject); // { a: 1, b: 2 }
Different ways to copy an object or an array
Shallow copy
Using the spread operator
The spread operator (...) is a concise way to create a shallow copy of an array or an object.
// Shallow copy of an arrayconst originalArray = [1, 2, 3];const shallowCopyArray = [...originalArray];console.log(shallowCopyArray); // [1, 2, 3]// Shallow copy of an objectconst originalObject = { a: 1, b: 2 };const shallowCopyObject = { ...originalObject };console.log(shallowCopyObject); // { a: 1, b: 2 }
Using Object.assign()
Object.assign() can also be used to create a shallow copy of an object.
const originalObject = { a: 1, b: 2 };const shallowCopyObject = Object.assign({}, originalObject);console.log(shallowCopyObject); // { a: 1, b: 2 }
Deep copy
Using structuredClone()
structuredClone() is a built-in function (Baseline across modern browsers and available in Node.js 17+) that creates a deep copy. It handles nested objects, arrays, Date, Map, Set, and circular references, but it cannot clone functions or DOM nodes (those throw a DataCloneError).
const originalObject = { a: 1, b: { c: 2 } };const deepCopyObject = structuredClone(originalObject);console.log(deepCopyObject); // { a: 1, b: { c: 2 } }
Using JSON.parse(JSON.stringify())
This can copy JSON-shaped data, but it is lossy: it drops unsupported object properties such as functions, undefined, and symbols; converts dates through toJSON(); does not preserve Map, Set, prototypes, or special numeric values faithfully; throws for BigInt and cycles; and can invoke custom toJSON() behavior.
const originalObject = { a: 1, b: { c: 2 } };const deepCopyObject = JSON.parse(JSON.stringify(originalObject));console.log(deepCopyObject); // { a: 1, b: { c: 2 } }
Using Lodash's _.cloneDeep()
Lodash is a popular utility library that provides a _.cloneDeep() method for deep copying objects and arrays.
const _ = require('lodash');const originalObject = { a: 1, b: { c: 2 } };const deepCopyObject = _.cloneDeep(originalObject); // { a: 1, b: { c: 2 } }
Other methods
Using recursion
For custom deep copy logic, you can implement a recursive function.
function deepCopy(obj) {if (obj === null || typeof obj !== 'object') {return obj;}if (Array.isArray(obj)) {return obj.map((item) => deepCopy(item));}const copy = {};for (const key in obj) {if (Object.hasOwn(obj, key)) {copy[key] = deepCopy(obj[key]);}}return copy;}const originalObject = { a: 1, b: { c: 2 } };const deepCopyObject = deepCopy(originalObject);console.log(deepCopyObject); // { a: 1, b: { c: 2 } }
Further reading
- MDN Web Docs: Spread syntax
- MDN Web Docs: Object.assign()
- MDN Web Docs: structuredClone()
- Lodash documentation: _.cloneDeep
- MDN Web Docs: JSON.parse()
- MDN Web Docs: JSON.stringify()