700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > JS学习笔记(九)深拷贝浅拷贝【Array Object为例】

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

时间:2018-09-14 11:26:01

相关推荐

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

JS学习笔记(九)

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

文章目录

JS学习笔记(九)一、赋值&复制二、浅拷贝(shallow copy)1. 什么是浅拷贝2. 数组的浅拷贝(1)介绍(2)数组浅拷贝的常见方法 2. 对象的浅拷贝的常见方法 三、深拷贝1. 什么是深拷贝2. 深拷贝介绍3. 深拷贝的常见方法 四、浅拷贝和深拷贝对比结尾

一、赋值&复制

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

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高级程序设计》,如有错误,欢迎评论区指正。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。