If you plan on coding with JavaScript, you need to understand how objects work. Objects are one of the most important elements of JavaScript, and a deep understanding of objects will always be useful.
It’s important to understand how to clone an object in JavaScript correctly. It is possible to create a shallow copy and a deep copy of an object. A shallow copy of an object references the original. So any changes made to the original object will be reflected in the copy. A deep copy is a copy of all elements of the original object. Changes made to the original object will not be reflected in the copy. In this article, you will create deep copies of objects using the Lodash library.
To complete this tutorial, you will need the following:
package.json
file. This article How to Use Node.js Modules with npm and package.json can help you with this.If you create a function that takes in an object and alters it, you may want to create a copy of the object and change the copy instead of mutating the original object.
Initialize a new object and assign it to the variable testObject
. This object should have letters a
, b
, and c
as keys and 1
, 2
, and 3
as values, respectively.
Create the object in JavaScript:
let testObject = {
a: 1,
b: 2,
c: 3
};
Now, try to create a copy of this object to manipulate by assigning the testObject
to a new variable called testObjectCopy
:
let testObject = {
a: 1,
b: 2,
c: 3
};
let testObjectCopy = testObject;
Change the value for the key a
in testObject
. Set it equal to 9
:
let testObject = {
a: 1,
b: 2,
c: 3
};
let testObjectCopy = testObject;
testObject.a = 9;
You may expect this change to only be reflected in the testObject
object. Use a console.log
statement to check what the value for a
is in testObjectCopy
:
let testObject = {
a: 1,
b: 2,
c: 3
};
let testObjectCopy = testObject;
testObject.a = 9;
console.log(testObjectCopy.a);
This console.log
statement will print 9
to the console, despite referencing testObjectCopy
and not testObject
. This is because creating the new variable testObjectCopy
doesn’t create a testObject
copy. Instead, it’s referencing the testObject
. Any changes you make to the original object will be reflected in the assumed copy and vice versa.
Reassigning objects to new variables only creates a shallow copy of the original object. In the next step, you will explore how looping through an object might be a possible solution to creating deep copies.
Looping through the object and copying each property to a new object may seem like a viable solution. To test this, create a function called copyObject
that takes an argument called object
:
const copyObject = object => {
};
Within copyObject
, declare a variable called copiedObj
which will hold an empty object:
const copyObject = object => {
let copiedObj = {};
};
Create a for
loop for each key in object
. Set the key/value pairs in copiedObj
equal to those in object
:
const copyObject = object => {
let copiedObj = {};
for (let key in object) {
copiedObj[key] = object[key];
}
};
For the final step in this copyObject
function, return copiedObj
:
const copyObject = object => {
let copiedObj = {};
for (let key in object) {
copiedObj[key] = object[key];
}
return copiedObj;
};
With copyObject
in place, create an object called testObject
and pass it in as a parameter for copyObject
:
const copyObject = object => {
let copiedObj = {};
for (let key in object) {
copiedObj[key] = object[key];
}
return copiedObj;
};
const testObject = {
a: 5,
b: 6,
c: {
d: 4
}
};
copyObject(testObject);
To see the results of the copyObject
function, use console.log
to see the output of copyObject(testObject)
printed to the console:
console.log(copyObject(testObject));
This will produce this output:
Output{ a: 5, b: 6, c: { d: 4 } }
It may seem like looping through the testObject
to create a copy produced the desired outcome. But there are several reasons why this approach won’t give you the results you’re looking for:
for
loops and Object.keys
.Object.prototype
method, which is not what you want when you copy an object. This means that whatever changes you make to the original object will be reflected in the copied object.configurable
or writable
to false
, the property descriptors in the copied object will default to true
.Looping through objects allows you to create shallow copies, but it isn’t possible to create deep copies using this method. Thankfully, there is a library available that offers a solution to creating deep copies.
For simple objects that only store primitive types like numbers and strings, shallow copying methods like the one above will work. However, if your object features references to other nested objects, the actual object won’t be copied. You would only be copying the reference.
For a deep copy, one great option is to use reliable external libraries like Lodash. Lodash is a library that offers two different functions that allow you to do shallow copies and deep copies. These are clone
and clonedeep
.
To test out the Lodash clone
and clonedeep
functions, you will need to install Lodash first:
- npm install --save lodash
With lodash now installed, use the require()
function to now access all the functions that Lodash has too offer:
const _ = require('lodash');
Now you can use the clone
and clonedeep
functions in your code. Create an object called externalObject
. Give a key animal
with the value of 'Gator'
:
const externalObject = {
animal: 'Gator'
};
Create another object called originalObject
. originalObject
will store seven properties with different values in each. The property d
references externalObject
which has the property of animal
and a value of 'Gator'
.
const originalObject = {
a: 1,
b: 'string',
c: false,
d: externalObject
};
clone
Declare a constant variable shallowClonedObject
and assign it to a shallow copy of originalObject
using the Lodash clone
function:
const shallowClonedObject = _.clone(originalObject);
Reassign the value of the animal
key in externalObject
. Set it equal to 'Crocodile'
. Use two console.log
statements to print both originalObject
and shallowClonedObject
to the screen:
externalObject.animal = 'Crocodile';
console.log(originalObject);
console.log(shallowClonedObject);
The output of this code will look like this:
Output{ a: 1, b: 'string', c: false, d: { animal: 'Crocodile' } }
{ a: 1, b: 'string', c: false, d: { animal: 'Crocodile' } }
Assigning the animal
property in externalObject
to a new value will change both originalObject
and shallowClonedObject
. The console.log
statements will show this. This happens because the shallow clone was only able to copy the reference to the externalObject
instead of creating a brand new object.
clonedeep
You can create a deep copy by using the Lodash clonedeep
function:
const deepClonedObject = _.clonedeep(originalObject);
With deepClonedObject
in place, reassign the value of the animal
key in externalObject
to be equal to 'Lizard'
.
Again, use two console.log
statements to print both originalObject
and deepClonedObject
to the screen:
externalObject.animal = 'Lizard';
console.log(originalObject);
console.log(deepClonedObject);
The output of this code will look like this:
Output{ a: 1, b: 'string', c: false, d: { animal: 'Lizard' } }
{ a: 1, b: 'string', c: false, d: { animal: 'Crocodile' } }
The 'animal'
property in the originalObject
changes, but for the
deepClonedObject
, it remains as 'Crocodile'
since the entire object was copied separately instead of copying the reference. Using the clonedeep
function allows you to successfully create deep copies of objects.
It’s important to understand how to deep clone objects in JavaScript. You created shallow copies of objects by reassigning and looping through objects. You also used the Lodash library to create both shallow and deep copies of objects.
If you would like to learn more about objects in JavaScript, this Understanding Objects in JavaScript tutorial is a great place to start. If you’d like to take this a step further and learn how to copy object methods, the Copying Objects in JavaScript article can point you in the right direction.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!