当前位置:网站首页>深拷贝与浅拷贝
深拷贝与浅拷贝
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)边栏推荐
- 2022年暑假ACM热身练习1(总结)
- How to modify the color of a line of text in the elemtnui table (elemtnui table modifies the color of a line of text)
- 使用leaflet仿原神提瓦特大地图制作日记
- 使用bat自动执行cmd命令(多个命令或单个命令)
- Node的数据库编程(MySQL),增删改查
- Uni app wechat applet - Mall (7) - Product Details
- (四)运算符
- 【ElenmentUI el-date-picker日期选择器,结束时间不得早于开始时间,且只能选择距开始时间指定天数的日期】
- JSX compilation
- 小程序嵌入网页向小程序跳转并传参,微信小程序中实现公众号授权获取openId
猜你喜欢

js替换字符串某个字符,js修改字符串中指定字符

object-fit:cover; It doesn't work in the applet. How to deal with the deformation of the applet image

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

JSX compilation

数据库连接池、sequelize实现增删改查等操作

ModelArts-图像分类and物体检测

Single page application spa and multi page application MPa

Use bat to automatically execute CMD commands (multiple commands or a single command)

uni-app微信小程序——商城(7)——商品详情

mock平台的使用说明
随机推荐
P6-day01-general attempt (P4 review)
Day11 serializer
网站如何统计访问人数?51LA如何安装使用?
Collection and summary of penetration test information
object-fit:cover;在小程序中不起作用,小程序图片变形了如何处理
TCP与UDP,TCP服务器与客户端,UDP服务器与客户端
The C Programming Language (2nd)--笔记--1.8
JSX syntax
Assemblage stylisé de cartes de commutation auto - encapsulées
Day14 view set and route
Win10 vscode 代码格式化设置与远程断点调试
Uni app wechat official account (4) - address management page
(10)文件包含
markdown编辑器语法——文字颜色、大小、字体与背景色的设置(转载)
uni-app微信小程序——商城(6)——我的主页
C Programming Language(2nd Edition)--读书笔记--1.5.1
Understand PHP from [Fifth space 2021] easycleanup_ session
当 std::bind 遇上 this
判断两个时间戳是否是同一天
今天的码农女孩总结了关于npm包管理和url模块的笔记