JS学习笔记(九)深拷贝&浅拷贝【Array、Object为例】

JS学习笔记(九)

本系列更多文章,可以查看专栏 JS学习笔记



一、赋值&复制

此部分赋值和复制的区别,仅针对引用类型

let arr = [1, 3, 5, 7, 9];
// 赋值,没有创建新对象
let arr2 = arr;
// 复制,会创建一个新对象
let arr3 = arr.slice();

// 输出数组
console.log("arr:", arr);
console.log("赋值arr2:", arr2);
console.log("复制arr3:", arr3);
// 比较数组对象
console.log("arr === arr2:", arr === arr2);
console.log("arr === arr3:", arr === arr3);

输出结果如下图所示:

在这里插入图片描述

区别:

  • 1.赋值: 仅仅将arr开辟的空间,给arr2进行共享
  • 2.复制: 重新为数组存储的元素开辟空间,只是元素值相同

在这里插入图片描述

深拷贝和浅拷贝,对于数组元素为原始类型(Number、String等)时,没有什么区别,区别在于元素为对象类型。


二、浅拷贝(shallow copy)

一般来说,
(1)原始类型(Number、String、BinInt、Null、Undefined、Boolean)的值存储在栈内存中(闭包除外);
(2)引用类型(Array、Function、Object),值一般存储在堆内存中(JS不允许直接访问堆内存)。

1. 什么是浅拷贝

浅拷贝,指会对引用类型对象本身进行复制,但不会复制对象内部的属性或元素。
注: 如果引用类型对象是数组类型,且其中存储的数据类型是原始类型,则浅拷贝或深拷贝效果一致【将在本文最后进行展示】

2. 数组的浅拷贝

(1)介绍

const arr = [{ name: "张三" }, { name: "李四" }];
const arr2 = arr.slice();
// 输出数组
console.log(arr);
console.log(arr2);
// 比较数组引用值
console.log("arr === arr2", arr === arr2);
// 比较数组属性值
console.log("arr[0] === arr2[0]", arr[0] === arr2[0]);
console.log("arr[1] === arr2[1]", arr[1] === arr2[1]);

数组的浅拷贝,如下图所示:

在这里插入图片描述
在这里插入图片描述

观察上图运行结果可知,浅拷贝仅会创建一个新数组(新的堆地址)存储原数组的值,本质上内部存储的元素是同一个。


(2)数组浅拷贝的常见方法

const arr = [{ name: "张三" }, { name: "李四" }];

方式1:Array.slice()方法

const arr2 = arr.slice();

方式2:Array.prototype.concat()方法

const arr2 = arr.concat();

方式3:ES6拓展运算符...

用途:用于将数组转换成以逗号分隔开的参数序列

const arr2 = [...arr];

方式4:for循环、for-of循环、while循环等

注:以下仅为一维数组示例代码

// for循环
const arr2 = [];
for (let i = 0; i < arr.length; i++) {
	arr2[i] = arr[i];
}

// for-of循环
const arr2 = [];
let i = 0;
for (let value of arr) {
	arr2[i++] = value;
}

// while循环
const arr2 = [];
let i = -1;
while (++i < arr.length) {
	arr2[i] = arr[i];
}

方式5:Object.assign()方法

用途:将一个或多个源对象,复制给目标对象,返回修改后的对象

const arr2 = Object.assign([], arr);

更多常见方法待补充中…


2. 对象的浅拷贝的常见方法

本质上与数组的浅拷贝一致

对象浅拷贝测试代码,运行结果如下图所示

在这里插入图片描述

const obj = { arr1: [1, 3, 5], arr2: [2, 4, 6] };

方式1:ES6拓展运算符...

const obj2 = { ...obj };

方式2:Object.assign()方法

用途:将一个或多个源对象,复制给目标对象,返回修改后的对象

const obj2 = Object.assign({}, obj);

更多常见方法待补充中…


三、深拷贝

1. 什么是深拷贝

深拷贝,指不仅复制引用类型对象本身,还会对对象的属性或元素进行复制
注: 如果引用类型对象是数组类型,且其中存储的数据类型是原始类型,则浅拷贝或深拷贝效果一致【将在本文最后进行展示】

2. 深拷贝介绍

以下为数组类型深拷贝为例,进行简单介绍

const arr = [{ name: "张三" }, { name: "李四" }];
const arr2 = structuredClone(arr);
// 输出数组
console.log(arr);
console.log(arr2);
// 比较数组引用值
console.log("arr === arr2", arr === arr2);
// 比较数组元素
console.log("arr[0] === arr2[0]", arr[0] === arr2[0]);
console.log("arr[1] === arr2[1]", arr[1] === arr2[1]);
// 比较数组元素值
console.log(
	"arr[0].name === arr2[0].name ",
	arr[0].name === arr2[0].name
);

数组的深拷贝,如下图所示:

在这里插入图片描述
上图可以看出,不仅对象本身进行了复制,其元素也进行了复制

在这里插入图片描述

观察上图运行结果可知,深拷贝不仅引用值会复制,其元素的值也会进行复制,仅有不可修改的原始类型的值及其地址不变。


3. 深拷贝的常见方法

const arr = [{ name: "张三" }, { name: "李四" }];

方式1:window.structuredClone()方法【适用于Array和Object】

const arr2 = structuredClone(arr); // window可省略

若对象的属性或者元素为自定义对象,则使用 window.structuredClone() 进行深拷贝后会变成普通对象
方式2:利用JSON.parse()和JSON.stringify()方法【适用于Array和Object】

const arr2 = JSON.parse(JSON.stringify(arr));

更多常见方法待补充中…


四、浅拷贝和深拷贝对比

上文中反复提到,当数据类型是原始类型,则浅拷贝或深拷贝效果一致

下文中,以对象中属性为原始类型为例

const obj = { name: "Jack", age: 18 };
// 浅拷贝
const obj2 = Object.assign({}, obj);
// 深拷贝
const obj3 = JSON.parse(JSON.stringify(obj));
// 输出对象
console.log("obj", obj);
console.log("obj2", obj2);
console.log("obj3", obj3);
// 比较对象引用值
console.log("obj === obj2", obj === obj2);
console.log("obj === obj3", obj === obj3);
// 比较对象中的属性值
console.log("obj.name === obj2.name", obj.name === obj2.name);
console.log("obj.name === obj3.name", obj.name === obj3.name);

以上代码,运行效果如下图所示:

在这里插入图片描述


结尾

部分内容参考《ECMAScript 6 入门》《JavaScript权威指南》《JavaScript高级程序设计》,如有错误,欢迎评论区指正。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在SystemVerilog中,深拷贝浅拷贝是指在复制对象时是否复制对象的内容。 浅拷贝是指仅复制对象的引用,而不复制对象的内容。当进行浅拷贝时,源对象和目标对象将指向同一个内存位置。如果修改了其中一个对象的内容,另一个对象也会受到影响。例如,在SV中,如果复制一个包含句柄的类对象,那么句柄将被复制,但实际对象不会被复制。这意味着修改其中一个对象的属性将影响另一个对象的属性。 深拷贝是指复制对象的内容和数据成员。在进行深拷贝时,每一个数据成员(包括嵌套的对象)都会被复制到新的对象中。这样,源对象和目标对象将拥有独立的内存空间,彼此之间的修改互不影响。在SV中,为了实现深拷贝,通常需要自定义`copy`函数来复制每一个数据成员。 需要注意的是,深拷贝可能会产生更多的内存开销,因为每个数据成员都需要复制。而浅拷贝则更加高效,因为只复制了引用。 综上所述,在SystemVerilog中,深拷贝浅拷贝是指复制对象时是否复制对象的内容。深拷贝会复制对象的内容和数据成员,而浅拷贝仅复制对象的引用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【sv中浅拷贝深拷贝】](https://blog.csdn.net/m0_56242485/article/details/123189393)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [SV学习笔记—浅复制和深复制的区别详解](https://blog.csdn.net/qq_41337361/article/details/122845943)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

想要大口炫榴莲

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

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

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

打赏作者

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

抵扣说明:

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

余额充值