Home >Web Front-end >JS Tutorial >Shallow vs. Deep Copying in JavaScript
Copying JavaScript objects is not as simple as it seems. Understanding how objects and references work during this process is critical to web developers and can save hours of debugging time. This becomes increasingly important when you use large stateful applications, such as those built in React or Vue.
Shallow copy and deep copy refer to how we create copies of objects in JavaScript and what data we create in "Copy". In this article, we will dig deep into the differences between these methods, explore their practical applications, and uncover potential pitfalls that may arise when using them.
Shallow copy refers to the process of creating a new object, which is a copy of an existing object whose properties refer to the same numerical value or object as the original object. In JavaScript, this is usually achieved using methods such as Object.assign()
or expansion syntax ({...originalObject}
). Shallow copy creates only new references to existing objects or values, and does not create deep copy, meaning that nested objects are still referenced, not duplicates.
Let's take a look at the following code example. The newly created object shallowCopyZoo
is a copy of zoo
created by expanding the operator, which has some unexpected consequences.
<code class="language-javascript">let zoo = { name: "Amazing Zoo", location: "Melbourne, Australia", animals: [ { species: "Lion", favoriteTreat: "?", }, { species: "Panda", favoriteTreat: "?", }, ], }; let shallowCopyZoo = { ...zoo }; shallowCopyZoo.animals[0].favoriteTreat = "?"; console.log(zoo.animals[0].favoriteTreat); // "?",而不是 "?"</code>
But let's see what exactly is in shallowCopyZoo
. The properties name
and location
are the original values (strings), so their values are copied. However, the animals
property is an array of objects, so what is copied is a reference to that array, not the array itself.
You can use the strict equality operator (===
) to test this quickly (if you don't believe me). Only when an object refers to the same object, one object is equal to another object (see Primitive Data Types and Reference Data Types). Note that the animals
attributes are equal in both, but the object itself is not equal.
<code class="language-javascript">let zoo = { name: "Amazing Zoo", location: "Melbourne, Australia", animals: [ { species: "Lion", favoriteTreat: "?", }, { species: "Panda", favoriteTreat: "?", }, ], }; let shallowCopyZoo = { ...zoo }; shallowCopyZoo.animals[0].favoriteTreat = "?"; console.log(zoo.animals[0].favoriteTreat); // "?",而不是 "?"</code>
This can cause potential problems in the code base and is especially difficult when dealing with large modifications. Modifying nested objects in shallow replicas also affects the original object and any other shallow replicas because they all share the same reference.
Deep copy is a trick to create a new object that is an exact copy of an existing object. This includes copying all its properties and any nested objects, rather than references. Deep cloning is useful when you need two separate objects that do not share references, ensuring that changes to one object do not affect the other.
Programmers often use deep cloning when dealing with application state objects in complex applications. Creating a new state object without affecting the previous state is critical to maintaining application stability and correctly implementing the undo/redo functionality.
JSON.stringify()
and JSON.parse()
for deep copyA popular and library-free deep copy method is to use the built-in JSON.stringify()
and JSON.parse()
methods.
parse(stringify())
The method is not perfect. For example, special data types such as Date
will be converted to strings, and undefined values will be ignored. As with all options in this article, you should consider it based on your specific use case.
In the following code, we will use these methods to create a deepCopy
function to deeply clone an object. Then we copy the playerProfile
object and modify the copied object without affecting the original object. This demonstrates the value of deep replication in maintaining independent objects that do not share references.
<code class="language-javascript">console.log(zoo.animals === shallowCopyZoo.animals) // true console.log(zoo === shallowCopyZoo) // false</code>
There are also a variety of third-party libraries that provide deep replication solutions.
cloneDeep()
functions can handle loop references, functions, and special objects correctly. extend()
function of jQuery library [deep = true]
The
<code class="language-javascript">const playerProfile = { name: 'Alice', level: 10, achievements: [ { title: 'Fast Learner', emoji: '?' }, { title: 'Treasure Hunter', emoji: '?' } ] }; function deepCopy(obj) { return JSON.parse(JSON.stringify(obj)); } const clonedProfile = deepCopy(playerProfile); console.log(clonedProfile); // 输出与playerProfile相同 // 修改克隆的配置文件而不影响原始配置文件 clonedProfile.achievements.push({ title: 'Marathon Runner', emoji: '?' }); console.log(playerProfile.achievements.length); // 输出:2 console.log(clonedProfile.achievements.length); // 输出:3</code>Disadvantages of deep copy
Date
, RegExp
, DOM elements). For example, when deep copying an object containing a function, a reference to the function may be copied, but the closure of the function and its bound context will not be copied. Likewise, objects with special features may lose their unique properties and behavior when deeply replicated. JSON.parse(JSON.stringify(obj))
also have some limitations, such as not being able to handle functions correctly, circular references, or special objects. While there are some third-party libraries such as Lodash's _.cloneDeep()
that handle deep replication more efficiently, adding external dependencies for deep replication may not always be ideal. Thank you for taking the time to read this article. Shallow and deep replication are much more complex than any beginner might think. While there are many pitfalls in each approach, taking the time to review and consider these options will ensure that your application and data keeps what you want to look like.
The main difference between shallow and deep replication is the way they handle properties as objects. In shallow copy, the copied object shares the same reference to the nested object as the original object. This means that changes to nested objects will be reflected in the original object and the copy object. Deep replication, on the other hand, creates new instances of nested objects, meaning changes to nested objects in the replicated object do not affect the original object.
The expansion operator (…) in JavaScript is usually used for shallow copying. It copies all enumerable properties of one object to another. However, it only copies the first level attributes and references to nested objects. Therefore, changes to nested objects will affect the original object and the copied object.
Yes, you can use the JSON method to perform deep copying in JavaScript. A combination of JSON.stringify()
and JSON.parse()
methods creates a deep copy of an object. JSON.stringify()
Converts the object to a string, JSON.parse()
parses the string back to the new object. However, this method has some limitations because it does not copy the method and is not suitable for special JavaScript objects such as Date
, RegExp
, Map
, Set
, etc.
Shallow copy only replicates the first-level attributes and references to nested objects. Therefore, if the original object contains nested objects, changes to those nested objects will affect the original object and the copied object. This can lead to unexpected results and errors in the code.
Object.assign()
How does the method work in shallow copy? Object.assign()
method is used to copy the values of all enumerable properties of one or more source objects to the target object. It returns the target object. However, it performs shallow copying, which means it only copies the first level properties and references to nested objects.
The best way to deeply copy objects in JavaScript depends on the specific requirements of the code. If your object does not contain methods or special JavaScript objects, you can use a combination of JSON.stringify()
and JSON.parse()
methods. For more complex objects, you may want to use libraries like Lodash, which provide deep cloning functions.
No, the expansion operator in JavaScript only performs shallow copying. It copies the first level attribute and references to nested objects. To perform deep replication, you need to use another method or library.
Deep replication may consume more resources than shallow replication, especially for large objects. This is because deep copy creates new instances for all nested objects, which can take up more memory and processing power.
JSON.stringify()
and JSON.parse()
do not handle circular references and will throw an error. A circular reference occurs when an object's properties refer to the object itself. To handle circular references, you need to use a library that supports it, such as Lodash.
Understanding the difference between shallow and deep replication is critical to managing data in JavaScript. It affects how your objects interact with each other. If you are not careful, shallow copying can lead to unexpected results and errors, as changes to nested objects affect the original and copied objects. Deep copy, on the other hand, ensures that your copy object is completely independent from the original object.
The above is the detailed content of Shallow vs. Deep Copying in JavaScript. For more information, please follow other related articles on the PHP Chinese website!