在 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 方法,如下所示。
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()
方法
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()
方法后获得的相同输出。
深度复制 JavaScript 中的对象
在深度复制中,所有键值
对都将被复制到新对象中。要执行深度复制,我们可以使用 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
的属性。
Sahil is a full-stack developer who loves to build software. He likes to share his knowledge by writing technical articles and helping clients by working with them as freelance software engineer and technical writer on Upwork.
LinkedIn