JavaScript 中的深度复制数组


在本文中,您将学习深拷贝和浅拷贝的概念。 本文还将介绍在 JavaScript 中对数组执行深拷贝的方法。


JavaScript浅拷贝和深拷贝介绍

在 JavaScript 中,可以通过两种方式复制对象。 它们是深拷贝和浅拷贝。

首先,让我们讨论一下浅拷贝。 对象的浅表副本具有指向与源对象的属性相同的引用的属性。

此处,源对象是从中创建副本的对象。 由于该对象及其浅表副本共享相同的引用,因此对其中一个所做的更改将反映在另一个对象中。

让我们通过一个例子来理解它。

考虑一个对象 student1,其属性名为 name,值为 kevin。 接下来,创建另一个变量 student2,并为其赋值 student2。

let student1 = {
  name: "kevin"
}

let student2 = student1

在这里,我们只是做了一个 student1 对象的浅拷贝。 现在,让我们尝试将 name 属性的值更改为 student2 对象中的其他值。

例如,新值是 john。 当我们打印对象 student1 和 student2 时,值是相同的:john。

示例代码:

let student1 = {
  name: "kevin"
}

let student2 = student1

 student2.name = "john"

console.log(student1)
console.log(student2)

输出:

{
  name: "john"
}
{
  name: "john"
}

这就是对象的浅表副本的行为方式。 它可以更改源对象的属性,因为两个对象共享相同的引用。

然而,对象的深拷贝恰恰相反。 由于副本和源对象不指向相同的引用,因此更改对象的一个属性不会更改其他对象。

在下面的部分中,您将了解深层复制以及在 JavaScript 中实现它的方法。


使用 structuredClone() 方法在 JavaScript 中创建对象的深层副本

在 JavaScript 中创建对象的深拷贝的方法之一是使用 structuredClone() 方法。 该方法使用深度克隆对象的结构化克隆算法。

该方法将要克隆的对象作为参数。 让我们执行克隆。

例如,考虑上面的 student1 对象,它包含 name 属性的值 kevin。 接下来,使用 structuredClone() 方法并提供 student1 对象作为其参数。

最后,将该方法分配给变量 student2。 这使得 student2 对象成为 student1 对象的深拷贝。

接下来,将 student2 对象的属性更改为 john。

这次当您打印两个对象时,它们的属性值不同。 student1 对象的值为 kevin,而 student2 的名称属性为 john。

示例代码:

let student1 = {
  name: "kevin",

}

let student2 = structuredClone(student1)

student2.name = "john"

console.log(student1)
console.log(student2)

输出:

{
  name: "kevin"
}
{
  name: "john"
}

这就是我们如何使用 structuredClone() 方法在 JavaScript 中执行深层复制。


使用 JSON.parse() 和 JSON.stringify() 方法在 JavaScript 中创建对象的深拷贝

我们还可以使用 JSON.parse()JSON.stringify() 方法创建对象的深拷贝。 JSON.stringify() 方法将对象或值转换为字符串,而 JSON.parse() 方法通过解析 JSON 字符串来创建对象或值。

首先,我们可以使用 JSON.stringify() 方法将对象转换为字符串,然后我们可以使用 JSON.parse() 方法通过解析对象来创建对象的深拷贝。

例如,考虑同一个 student1 对象并使用 JSON.stringify() 方法将该对象转换为字符串。 然后,对结果使用 JSON.parse() 方法。

将表达式分配给变量 student2。 接下来,像上面那样更改第一个对象的属性并打印两个对象。

示例代码:

let student1 = {
  name: "kevin",

}


let student2 = JSON.parse(JSON.stringify(student1))

student2.name = "john"

console.log(student1)
console.log(student2)

输出:

{
  name: "kevin"
}
{
  name: "john"
}

我们可以看到这两个对象的属性值是不同的,也就是说我们创建了源对象的深拷贝。 因此,我们可以使用 JSON.parse()JSON.stringify() 方法在 JavaScript 中执行对象的深拷贝。

但是,我们在使用函数和对象时会遇到问题。 让我们实现一个包含函数和 Date() 对象的对象的深度克隆,以更清楚地了解问题。

将新字段添加到 student1 对象,如下例所示。

示例代码:

let student1 = {
  name: "kevin",
  age: function(){
        return 24;
  },
  enrolledDate: new Date()

}

接下来,使用 JSON.parse()JSON.stringify() 函数创建上述对象的深层副本。 然后,更改第一个对象的名称属性。 最后,打印两个对象。

示例代码:

let student2 = JSON.parse(JSON.stringify(student1))
student2.name = "john"

console.log(student1)
console.log(student2)

输出:

{
  name: 'kevin',
  age: [Function: age],
  enrolledDate: 2023-01-19T16:15:30.914Z
}
{ name: 'john', enrolledDate: '2023-01-19T16:15:30.914Z' }

在这里,我们可以在对象的深拷贝中看到一些值得注意的问题。 第一个问题是该函数缺少克隆对象。

另一个问题是嵌套对象new Date() 的类型发生了变化。 克隆后,新的 Date() 对象变为 String 类型。 您可以注意到日期前后的引号。

因此,我们在使用 JSON.parse()JSON.stringify() 方法对包含函数和类型的对象进行深拷贝时发现了一个问题。 我们将在本文的下一节中解决该问题。


使用 Lodash 库在 JavaScript 中创建对象的深拷贝

我们可以在使用 lodash 库克隆函数和嵌套对象时解决这个问题。 lodash 提供了一个方法 cloneDeep(),它以源对象为参数,对其进行深度克隆。

您可以使用以下命令安装库。

npm i -g lodash

例如,在代码顶部要求库。 将其分配给常量 _

使用常量调用 cloneDeep(),其中 student1 对象是参数。 像以前一样更改对象属性的值。 最后,打印两个对象。

示例代码:

const _=require('lodash')
let student1 = {
  name: "kevin",
  age: function() {
    return 24;
  },
  enrolledDate: new Date()

}


let student2 = _.cloneDeep(student1)

student2.name = "john"

console.log(student1)
console.log(student2)

输出:

{
  name: 'kevin',
  age: [Function: age],
  enrolledDate: 2023-01-23T15:02:56.059Z
}
{
  name: 'john',
  age: [Function: age],
  enrolledDate: 2023-01-23T15:02:56.059Z
}

最后,我们可以深度克隆对象并且仍然拥有函数和嵌套对象。 因此,我们可以使用 lodash 库在 JavaScript 中创建对象的深度克隆。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迹忆客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值