当前位置:网站首页>深拷贝与浅拷贝
深拷贝与浅拷贝
2022-07-17 00:07:00 【禾木白】
文章目录
前言
怎么区分深拷贝和浅拷贝呢?
let a = [0,1,2,3,4]
let b = a;
console.log(b); //[0,1,2,3,4]
a[0] =1;
console.log(b); //[1,1, 2, 3, 4] 根据上面的例子,b复制了a,当我们修改a的时候,b的值也跟着发生了变化,这就是浅拷贝。如果我们修改a后,b没有变化,那么它就是深拷贝了。
一、基本数据与引用数据类型
为什么我们修改了a,b也会跟着变化呢?
那就要涉及到基本数据类型与引用数据类型的概念了。
基本数据类型:number,string,boolean,null,underfined,symbol 以及es10新增的BigInt。
引用数据类型:object,array,function等。
- 基本数据类型名和值是存放在栈中的。
例如:let a = 1; b = a;
a= 1时会在栈内存中开辟内存存放对应名值。
b = a时栈内存会新开辟一个内存,存放b的值,两个变量拥有各自的空间互补干扰,所以我们修改b时a并不会受到影响。虽然b不受a影响,但这也算不上深拷贝,因为深拷贝本身只针对较为复杂的object类型数据。
- 引用数据类型--名和地址指针在栈内存中,值存在于堆内存中。

当obj1 = obj 进行拷贝,实际是在栈中开辟内存来存放obj1,对应值同为obj所对应的地址指针。
即为obj1与obj同指向堆内存中的同一个值。

当我们对obj[0] = 1进行数组修改时,由于obj与obj1指向的是同一个地址,所以自然obj1也受了影响,这就是所谓的浅拷贝了。

二、如何实现深拷贝?
1.通过JSON.stringify()和JSON.parse()

由上图可以看出,obj通过JSON.parse(JSON.stringify())给obj1赋值后,改变obj中属性值,obj1并没有随之变化,实现了深拷贝。
但是,这个方法也是有缺陷的:
let a={
name:'小小',
age:20,
num:undefined,
no:Symbol(1),
info:function(){return {address:'河北',iphone:'1234567'}}
}
let b = JSON.parse(JSON.stringify(a));
b //{name: "小小", age: 20}
a //{name: "笑笑", age: 20, num: undefined, no: Symbol(1), info: ƒ}如上可以看出, JSON.parse(JSON.stringify())不能复制function,undefined和symbol,同样也无法解决循环引用的对象,会造成数据的丢失。
2.通过递归方式遍历底层进行深拷贝
let obj={
name:'小小',
age:20,
num:undefined,
no:Symbol(1),
new:{name:'title',id:[2,[3,4]]},
info:function(){return {address:'河北',iphone:'1234567'}}
}
const clone = (obj)=>{
let data= typeof obj === 'object' ? {}:[];
if(obj && typeof obj ==='object'){
for(let key in obj){
if(obj[key] && typeof obj[key]==='object'){
data[key] = clone(obj[key])
}else{
data[key] = obj[key]
}
}
}
return data;
}
let obj2 = clone(obj);
obj.new.name='value';
obj.new.id[1][0]=10;
console.log(obj2);
console.log(obj);
3. 通过jq的extend方法进行深拷贝
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。
let a={
name:'小小',
age:20,
num:undefined,
no:Symbol(1),
new:{name:'title',id:[2,[3,4]]},
info:function(){return {address:'河北',iphone:'1234567'}}
}
b=$.extend(true,[],a);
a.name="笑笑";
a.new.name="value";
a.new.id[1][0] = 10;
console.log(a,b); 
4.只能深度拷贝对象的第一层
- Object.assign() 对象的合并
- Array.slice()方法
- Array.concat()方法
- es6解构赋值
只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝。
关于JSON.parse(JSON.stringify())深拷贝的补充。
- obj里面有new Date(),深拷贝后,时间会变成字符串的形式。而不是时间对象;
- obj里有RegExp、Error对象,则序列化的结果会变成空对象{};
const a ={
name:'a',
date:new RegExp('\\w+'),
};
const b =JSON.parse(JSON.stringify(a));
a.name ='test'
console.log( a, b)- obj里有NaN、Infinity和-Infinity,则序列化的结果会变成nul。
const a ={
name:'a',
date:NaN,
};
const b =JSON.parse(JSON.stringify(a));
a.name ='test'
console.log(a, b)边栏推荐
- 网站被黑,通过百度/搜狗等搜索关键词访问跳转到其他网站怎么办?
- The C Programing Language-2nd--笔记--4.11.3
- 自己封裝的風格化的開關卡片組件
- 智能指针(shared_ptr、unique_ptr、weak_ptr)
- 鼠标右键菜单添加快速打开选项遇见的错误:
- JS replaces a character in the string, and JS modifies the specified character in the string
- JS数组常用方法
- MoveIt2——4.机器人模型和机器人状态
- 分布式之数据库和缓存双写一致性方案解析(转载)
- uni-app微信小程序——商城(8)——订单详情
猜你喜欢

Uni app wechat applet - Mall (3) - Mall Homepage

Codeforces round #664C

From catf1ag two-hour AK match pwn/attack killing, summarize the common command guide of emergency response

JSX 语法

使用bat自动执行cmd命令(多个命令或单个命令)

自己封装的风格化的开关卡片组件

Win10 vscode 代码格式化设置与远程断点调试

uni-app微信公众号(1)——网页授权登录

Use leaflet to copy the original shentiwa Mega map to make a diary
![[elementui El date picker date selector, the end time must not be earlier than the start time, and only the date of the specified number of days from the start time can be selected]](/img/73/af7ca3f670ffee18081b9ca6a9ccf6.png)
[elementui El date picker date selector, the end time must not be earlier than the start time, and only the date of the specified number of days from the start time can be selected]
随机推荐
Node的数据库编程(MySQL),增删改查
学习STM32F103时涉及的C语言知识汇总(仅链接)
TCP与UDP,TCP服务器与客户端,UDP服务器与客户端
JSX syntax
数据库连接池、sequelize实现增删改查等操作
let和var的区别
win10解压文件时,出错:不能创建符号链接 你可能需要以管理员权限运行Winrar 客户端没有所需的特权
今天的码农女孩做了关于呼吸灯的练习、受控组件和高阶组件的简答题
(三)传递参数
uniapp调用地图,进行位置查询,标记定位
everything搜索不到startup_lpc11x.s文件
2022年暑假ACM热身练习2(总结)
列表懒加载和图片懒加载
uni-app微信公众号(4)——地址管理页面
uni-app微信小程序——商城(4)——商家
MoveIt2——2.MoveIt在RViz中的快速入门
uni-app微信小程序——商城(3)——商城主页
Stack injection [strong net cup 2019] random note
(七)流程控制
使用bat自动执行cmd命令(多个命令或单个命令)