Javascript 简明教程
JavaScript - Shallow Copy
Shallow Copy
在 JavaScript 中,浅拷贝是数组或对象的重复,复制其顶级元素,但不是其嵌套结构。创建数组的浅拷贝时,常用方法包括使用展开运算符 ([…]), Array.from() 或 slice() 方法。
In JavaScript, a shallow copy is a duplication of an array or object that replicates its top-level elements, but not its nested structures. When creating a shallow copy of an array, common methods include using the spread operator ([…]), Array.from(), or the slice() method.
对于对象,展开运算符 ({…}) 和 Object.assign() 常用于执行此操作。需要注意的是,虽然顶级语句正在被复制,但原始结构中的任何嵌套对象或数组不会被克隆,而是在浅拷贝中保留它们的引用。
For objects, the spread operator ({…}) and Object.assign() are commonly used. It is important to note that while the top-level statements are being duplicated, any nested object or arrays that are within the original structure are not cloned, instead their references are retained in the shallow copy.
因此,在复制版本中对嵌套结构的修改会影响原始版本,反之亦然。对于深度克隆,即嵌套结构也被复制,需要 lodash 的 _.cloneDeep 等备用技术或库。
Consequently, modifications to nested structures in the copied version affect the original and vice versa. For deep cloning, where nested structures are also duplicated, alternative techniques or libraries such as lodash’s _.cloneDeep are required.
Deep Copy vs. Shallow Copy
存在两种复制对象或数组的方法:深度复制和浅复制。深度复制创建一个完全独立的副本,甚至包括嵌套结构;相反,浅复制只复制顶级元素,同时保留对嵌套元素的引用。
Two methods exist for duplicating objects or arrays: deep copying and shallow copying. Deep copying creates an entirely independent duplicate even including nested structures; conversely, shallow copying only replicates top-level elements while maintaining references to the nested ones.
虽然深度复制保证完全独立,但浅复制证明了更高的内存效率和速度,但代价是:嵌套结构中的修改会影响原始对象和复制的对象。任务要求决定了选择:对于完全独立,深度复制是首选;但是,当效率至上并且可以保留嵌套引用时,浅复制成为最佳选择。
While deep copying guarantees complete independence, shallow copy proves more memory-efficient and faster but at a cost: modifications in nested structures impact both original and copied objects. Task requirements dictate the choice: for total independence, deep copying is preferred; however, when efficiency is paramount and nested references can be preserved, shallow copying becomes the optimal option.
Examples
Example 1: Shallow copy using Object assign() method
在以下示例中,我们使用 Object.assign() 方法创建一个对象的浅拷贝。
In the following example, we use the Object.assign() method create a shallow copy of an object.
<!DOCTYPE html>
<html>
<body>
<h2>Shallow copy using Object.assign() method</h2>
<p>Original Object:</p>
<p id="originalObject"></p>
<p>Copied Object:</p>
<p id="copiedObject"></p>
<script>
const originalObject = { name: "Alice", age: 30 };
const copiedObject = Object.assign({}, originalObject);
document.getElementById("originalObject").textContent = JSON.stringify(originalObject);
document.getElementById("copiedObject").textContent = JSON.stringify(copiedObject);
</script>
</body>
</html>
Example 2: Shallow copy using spread operator
在此示例中,我们使用展开运算符 (…) 创建数组的浅拷贝。
In this example we use the spread operator (…) to creating a shallow copy of an array.
<!DOCTYPE html>
<html>
<body>
<h2>Shallow copy using spread operator (...)</h2>
<p>Original Array:</p>
<p id="originalArray"></p>
<p>Copied Object:</p>
<p id="copiedArray"></p>
<script>
const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];
document.getElementById("originalArray").textContent = JSON.stringify(originalArray);
document.getElementById("copiedArray").textContent = JSON.stringify(copiedArray);
</script>
</body>
</html>
Example 3:Shallow copy of object with array
在下面的示例中,Object.assign() 和 Array.prototype.slice() 的组合被用于创建对象的浅拷贝,强调了对对象结构内数组的正确处理。
In the example below, a combination of Object.assign() and Array.prototype.slice() is used to create a shallow copy of an object, emphasizing proper handling of arrays within the object structure.
<!DOCTYPE html>
<html>
<body>
<h2>Shallow copy using array slice() method</h2>
<p>Original Object:</p>
<p id="originalObject"></p>
<p>Copied Object:</p>
<p id="copiedObject"></p>
<script>
const originalObject = { name: "Bob", hobbies: ["reading", "coding"] };
const copiedObject = Object.assign({}, originalObject, { hobbies: originalObject.hobbies.slice() });
document.getElementById("originalObject").textContent = JSON.stringify(originalObject);
document.getElementById("copiedObject").textContent = JSON.stringify(copiedObject);
</script>
</body>
</html>
Example 4: Shallow Copy with Nested Objects
在本示例中,我们将演示如何使用 JavaScript 的 JSON.stringify 和 JSON.parse 方法创建具有嵌套属性的对象的浅拷贝。原始对象包含具有诸如 name 和 address 等属性的嵌套结构。地址进一步由诸如街道和城市等属性组成。然后,我们使用 JSON.stringify 将原始对象转换为格式化的 JSON 字符串,然后应用 JSON.parse 将字符串解析回新对象,从而创建浅拷贝。
In this example we demonstrate creating of shallow copies of an object with nested properties using the JSON.stringify and JSON.parse methods of JavaScript. The original object contains of a nested structure which has properties like name and address. Address further consists of properties like street and city. We then use JSON.stringify to convert the original object into a JSON formatted string & then apply the JSON.parse to parse the string back into a new object thereby creating a shallow copy.
<!DOCTYPE html>
<html>
<body>
<h2>Shallow Copy with Nested objects using JSON.stringify & JSON.parse</h2>
<p>Original Object:</p>
<pre id="originalObject"></pre>
<p>Copied Object:</p>
<pre id="copiedObject"></pre>
<script>
const originalObject = {
name: "Charlie",
address: {
street: "123 Main St",
city: "New York"
}
};
const copiedObject = JSON.parse(JSON.stringify(originalObject));
document.getElementById("originalObject").textContent = JSON.stringify(originalObject, null, 2);
document.getElementById("copiedObject").textContent = JSON.stringify(copiedObject, null, 2);
</script>
</body>
</html>
Example 5: Shallow copy impact of modification
说明通过 JavaScript 的 Object.assign() 方法创建的浅拷贝上的修改的影响,以下代码最初提供了一个原始对象。原始对象具有名为“name”和“age”的属性,旁边是其相应的浅拷贝。接下来,我们观察此代码如何更改复制对象中的“age”属性。随后,代码对原始对象和复制对象修改后的状态进行说明。这个实例强调了对浅拷贝的改动尽管在复制对象中隔离,但不会影响基本对象;因此,它确认了一种特殊行为,其中顶层属性被浅拷贝捕获,同时保持主实例和次实例之间的独立性。
Illustrating the impact of modifications on a shallow copy created via JavaScript’s Object.assign() method, the following code initially presents an original object. The original object features properties named "name" and "age," side by side with its corresponding shallow copy. Next, we observe how this code alters the "age" property of our copied object. Subsequently, the code presents an exposition of both the original and copied objects' states post-modification. This instance accentuates that alterations to the shallow copy despite isolating within its duplicated object do not influence the base object; it thereby confirms a peculiar behaviour wherein top-level properties are captured by shallow copies while preserving independence between primary and secondary instances.
<!DOCTYPE html>
<html>
<body>
<h2>Shallow Copy impact of modification</h2>
<h3>Before Modification</h3>
<p>Original Object</p>
<pre id="originalObjectBefore"></pre>
<p>Copied Object</p>
<pre id="copiedObjectBefore"></pre>
<h3>After Modification</h3>
<p>Original Object</p>
<pre id="originalObjectAfter"></pre>
<p>Copied Object</p>
<pre id="copiedObjectAfter"></pre>
<script>
const originalObject = { name: "Alice", age: 30 };
const copiedObject = Object.assign({}, originalObject);
document.getElementById("originalObjectBefore").textContent = JSON.stringify(originalObject, null, 2);
document.getElementById("copiedObjectBefore").textContent = JSON.stringify(copiedObject, null, 2);
copiedObject.age = 40;
document.getElementById("originalObjectAfter").textContent = JSON.stringify(originalObject, null, 2);
document.getElementById("copiedObjectAfter").textContent = JSON.stringify(copiedObject, null, 2);
</script>
</body>
</html>
Importance of Shallow Copy
为了保留原始数据结构并有效管理内存,必须严格理解 JavaScript 中的浅拷贝:它复制了顶层元素,实现了平衡的概念。这种理解使非破坏性操作任务得以实现;例如,数组排序。此外,它简化了诸如撤消/重做功能之类的特性实现过程,同时显著增强了整体用户体验——这确实是一个不可或缺的角色。能够熟练地处理实际应用程序中的更改的浅拷贝能够维护数据完整性:在某些情况下,需要将修改与原始对象隔离开来时,这是一个至关重要的方面。
To preserve the original data structure and manage memory efficiently, one must critically understand shallow copying in JavaScript: it duplicates top-level elements a concept that achieves balance. This understanding empowers non-destructive manipulation tasks; for example, array sorting. Furthermore, it simplifies feature implementation processes like undo/redo functionalities, all while significantly enhancing overall user experience – an integral role indeed. Shallow copies possessing the capacity to adeptly handle alterations in practical applications maintain data integrity: a crucial aspect when isolating modifications from an original object is necessary in certain scenarios.