在 JavaScript 中如何复制对象
各种编程语言具有各种数据结构,允许你在内存中组织和存储数据。每个数据结构的工作方式都是独一无二的。例如,在 C++ 和 Java 中,我们有 Hashmap 以键值形式存储数据。同样,在 JavaScript 中,我们有一个称为对象的数据结构,它允许你以键值
格式存储数据。
在访问数据时,这些对象会派上用场。我们可以使用对象的键轻松访问对象中的任何数据。在本文中,我们将看到在 JavaScript 中复制对象的各种方式。
请注意
JavaScript 对象是可变的,并且存储为引用。如果你已经创建了一个对象并希望将其分配给其他某个对象,那么该对象现在将保存该对象的地址。由于我们将对象的引用存储在另一个对象中,然后使用这个新对象,我们可以轻松地更改原始对象中存在的值。
var a = {
"name": "Adam",
"company": "Google"
}
var b = a;
b.name = "Sam"
console.log(a.name, b.name);
输出:
Sam Sam
从上面的示例中可以看出,将一个对象分配给另一个对象不会复制对象本身。它只会将旧对象的地址存储到新对象中。
在 JavaScript 中有两种复制对象的方法。一种方式称为浅拷贝,另一种方式称为深拷贝。为了实现这些方法,我们可以使用一些 JavaScript 方法,如下所示。
在浅拷贝中,只有出现在对象第一层的键值
对才会被复制到新对象中。并且所有嵌套的元素或属性,例如数组或内部的另一个对象,都不会被复制,而是将它们的引用存储在此对象中。
在浅拷贝中,原始对象的一些属性也会受到影响。要理解这一点,请看下面的例子。
var obj1 = {
"firstName": "James",
"lastName": "Bond",
"films": [
"No Time To Die",
"Spectre",
"Skyfall",
"Quantum of Solace"
],
"actors":{
"characters": {
"realName": "Daniel Craig",
"fakeName": "James Bond"
}
}
}
在这个例子中,我们有一个名为 obj1
的对象。要使用 JavaScript 对这个对象进行浅拷贝,我们可以使用 Object.assign()
和扩展运算符 ...
。让我们使用 JavaScript 中的以下方法对 obj1
执行浅拷贝。
Object.assign()
方法有两个参数。第一个参数是复制完成后将返回的 target
对象。第二个参数是我们要复制的对象:obj1
。在我们的例子中,我们将传递一个空对象 {}
作为目标。这是因为 obj1
中的所有元素都将被复制到这个空对象中。复制完成后,Object.assign()
将返回我们将存储在 obj2
变量中的新对象。
var obj2 = Object.assign({}, obj1);
稍后,我们将修改此对象的属性,我们将实际了解为什么将其称为浅拷贝。
obj2.firstName = "Camila";
obj2.films[0] = "abcccc";
obj2.actors.characters.realName = "Camila";
console.log(obj1);
console.log(obj2);
输出:
在这里,我们使用 obj2、firstName
、films[]
数组中的第一部电影和 actors.characters
对象中的 realName
属性更改三个值。然后我们打印这两个对象。
上图显示两个对象中只有 firstName
属性没有更改。另外两个属性 films[]
和 realName
在这两个对象中都发生了变化。这被称为浅拷贝,因为 firstName
属性是唯一的,而其他属性对于两个对象都是通用的,因为我们在这里存储地址。此处,仅复制存在于第一级的属性。
rest 运算符将把 obj1
的属性复制到 obj2
中。这类似于 Object.assign()
,我们浅拷贝对象的属性。要使用扩展运算符复制对象,你必须在扩展符号后写入对象名称。
var obj2 = {...obj1};
obj2.firstName = "Camila";
obj2.films[0] = "abcccc";
obj2.actors.characters.realName = "Camila";
你还将获得我们在使用 Object.assign()
方法后获得的相同输出。
在深度复制中,所有键值
对都将被复制到新对象中。要执行深度复制,我们可以使用 JSON.parse()
和 JSON.stringify()
方法。请注意,深层复制不会复制原型对象中存在的属性。
使用 JSON.stringify()
,我们将首先将整个对象(在本例中为 obj1
)转换为字符串,然后在 JSON.parse()
方法的帮助下,我们将解析将此字符串重新转换为 JSON 格式。
let obj2 = JSON.parse(JSON.stringify(obj1));
在这里,你可以修改 obj2
内的任何属性,这不会影响 obj1
内的属性。
obj2.firstName = "Camila";
obj2.films[0] = "abcccc";
obj2.actors.characters.realName = "Camila";
输出:
我们正在修改之前修改的相同值,现在你可以注意到,当我们更改 obj2
的属性时,它不会影响 obj1
的属性。
相关文章
Do you understand JavaScript closures?
发布时间:2025/02/21 浏览次数:108 分类:JavaScript
-
The function of a closure can be inferred from its name, suggesting that it is related to the concept of scope. A closure itself is a core concept in JavaScript, and being a core concept, it is naturally also a difficult one.
Do you know about the hidden traps in variables in JavaScript?
发布时间:2025/02/21 浏览次数:178 分类:JavaScript
-
Whether you're just starting to learn JavaScript or have been using it for a long time, I believe you'll encounter some traps related to JavaScript variable scope. The goal is to identify these traps before you fall into them, in order to av
How much do you know about the Prototype Chain?
发布时间:2025/02/21 浏览次数:150 分类:JavaScript
-
The prototype chain can be considered one of the core features of JavaScript, and certainly one of its more challenging aspects. If you've learned other object-oriented programming languages, you may find it somewhat confusing when you start
用 jQuery 检查复选框是否被选中
发布时间:2024/03/24 浏览次数:102 分类:JavaScript
-
在本教程中学习 jQuery 检查复选框是否被选中的所有很酷的方法。我们展示了使用直接 DOM 操作、提取 JavaScript 属性的 jQuery 方法以及使用 jQuery 选择器的不同方法。你还将找到许多有用的
jQuery 中的 Window.onload 与 $(document).ready
发布时间:2024/03/24 浏览次数:180 分类:JavaScript
-
本教程演示了如何在 jQuery 中使用 Window.onload 和 $(document).ready 事件。