How to clone JavaScript objects in depth

JavaScript provides many methods for copying objects, but not all methods provide deep copying. Learn the most effective method and find out all available options

Copying objects with JavaScript can be tricky. Some methods perform shallow copy, which is the default behavior in most cases.

Deep copy and shallow copy

Shallow copy successfully copiedbasic typeLike numbers and strings, but will not copy any object references recursively, but the newly copied object will reference the same object.

If an object references other objects, then executeShallow copyObject, youCopy referenceTo external objects.

When executing aDeep copy, Those onesExternal objects are also copiedTherefore, the new cloned object is completely independent of the old object.

Search how to deep clone objects in JavaScript on the Internet, you will find many answers, but the answer isNot always correct.

The easiest option: use Lodash

I recommend performing deep copying by relying on a well-tested, very popular and well-maintained library: Lodash.

Lodash provides a very convenientclonewithdeepcloneUsed to perform shallow and deep cloning functions.

Lodash has the following outstanding features:You can import individual functions separatelyReduce a lot of dependencies in your project.

In Node.js:

const clone = require('lodash.clone')
const clonedeep = require('lodash.clonedeep')

This is an example showing two functions in use:

const clone = require('lodash.clone')
const clonedeep = require('lodash.clonedeep')

const externalObject = { color: ‘red’, }

const original = { a: new Date(), b: NaN, c: new Function(), d: undefined, e: function () {}, f: Number, g: false, h: Infinity, i: externalObject, }

const cloned = clone(original)

externalObject.color = ‘blue’

console.info(‘⬇️ shallow cloning 🌈’) console.info( ‘✏️ Notice the i.color property we changed on original is also changed in the shallow copy’ ) console.log(original) console.log(cloned)

const deepcloned = clonedeep(original)

externalObject.color = ‘yellow’ console.log(’’) console.info(‘⬇️ deep cloning 🌈’) console.info(‘✏️ Notice the i.color property does not propagate any more’) console.log(original) console.log(deepcloned)

In this simple example, we first create a shallow copy, and then edit the i.color property, which is propagated to the copied object.

In deep cloning, this does not happen.

Object.assign()

Object.assign()Perform a shallow copy of the object, not a deep copy.

const copied = Object.assign({}, original)

As a shallow copy, the value will be cloned and the object reference (not the object itself) will be cloned, so if you edit the object properties in the original object, it will also be modified in the copied object because the referenced internal object is the same of:

const original = {
  name: 'Fiesta',
  car: {
    color: 'blue',
  },
}
const copied = Object.assign({}, original)

original.name = ‘Focus’ original.car.color = ‘yellow’

copied.name //Fiesta copied.car.color //yellow

Use the object spread operator

ThisSpread operatorIs anES6 / ES2015This function provides a very convenient way to perform shallow cloning, which is equivalent toObject.assign()do.

const copied = { ...original }

Wrong solution

You will find many suggestions on the Internet. This is something wrong:

Use Object.create()

Note: Not recommended

const copied = Object.create(original)

This is wrong, it does not perform any copying.

in contrast,originalObject is used asprototypeofcopied.

Obviously, it works, but behind the scenes it does not:

const original = {
  name: 'Fiesta',
}
const copied = Object.create(original)
copied.name //Fiesta

original.hasOwnProperty('name') //true
copied.hasOwnProperty('name') //false

see moreObject.create().

JSON serialization

Note: Not recommended

Some suggestions are converted toJSON format:

const cloned = JSON.parse(JSON.stringify(original))

But this will bring unintended consequences.

By doing this, you willloseThere is no equivalent type of any Javascript attributes in JSON, for exampleFunctionorInfinity. Any attribute assigned toundefinedWill be ignoredJSON.stringify, Causing them to be lost on the cloned object.

In addition, some objects will be converted to strings, such as Date objects (again, regardless of time zone, the default is UTC), Set, Map and many other objects:

JSON.parse(
  JSON.stringify({
    a: new Date(),
    b: NaN,
    c: new Function(),
    d: undefined,
    e: function () {},
    f: Number,
    g: false,
    h: Infinity,
  })
)

Parsing as JSON

This only works if you don't have any internal objects and functions, but only values.

Download mine for freeJavaScript beginner's manual


More js tutorials: