JavaScript之浅复制【拷贝】与深复制【拷贝】【二】
下面了解下什么浅复制【拷贝】和深复制【拷贝】,通过下面的阅读你将了解到:
1、什么是浅复制以及使用场景
2、什么是深复制以及使用场景
3、浅复制和深复制有哪些方式
复制代码
一、我们先来了解下,JavaScript基本知识,基本类型和引用类型
基本类型:number、string、boolean、null、undefined 后来es6又增加了一个基本类型symbol,目前基本类型为6个
引用类型:Object、 Function、Array
复制代码
什么是堆【heap】和 栈 【stack】
栈:自动分配内存,系统自动释放,里面包含值类型和引用类型的地址【引用对象】
堆:动态分配内存,大小不定,系统不会自动释放,里面存放引用类型的值【实例对象】
看个例子:
let a=1;
let b=a;
console.log(a)//1
console.log(b)//1
b=3;
console.log(b)//3
console.log(a)//1
复制代码
从例子得出结论:当值赋值给变量时,解析器确定是基本类型值还是引用类型值。基本数据类型,是值访问的,并且可以操作保存在变量中的实际值。基本类型复制的时候,就是在栈中开辟一个新的存储区域用来存储变量。所以其中一个值变化,不会影响另一个值.
如例子:虽然b=3发生了改变,但a输出结果还是1,印证上面的结论.
再来看下个例子:
let obj={name:'zjl',remark:'zjl'};
let anotherObj=obj;
anotherObj.name='lisi'
console.log(obj);//{name:'lisi',remark:'zjl'};
复制代码
从上面的例子中,可以看出一个值发生的改变也影响到了另一个.
如上:obj的name由zjl变为了lisi,这是为什么呢?
引用类型值【实例对象】,是存放在堆内存中的对象。与其它语言不同,JavaScript中,不允许直接访问内存位置及不能直接操作内存空间。实际操作的是对象的引用【指针】,不是实际的对象。
补充:对象引用是栈中的地址,复制对象时,相当于在栈中开辟新的一块区域存放这个地址(指针),这个指针指向同一块堆内存位置。所以其中一个指针对象发生改变,另一个也会发生改变。
总结下区别,两者的主要区别就是,基本类型是值传递,引用类型是地址传递
二、下面就,常见的数组【Array】和对象【Object】,来讨论下深浅复制
- 浅复制:拷贝的是引用对象--拷贝的是栈中的地址【对象的引用】,栈中指针指向同一块堆内存【实例对象】,因此修改一个引用对象,另一个引用对象也随之修改.就像你拿了一把钥匙打开一扇门,别人拿到你这把钥匙也能打开这扇门,并且从房间拿走了东西,你拿到这把钥匙开门后发现东西少了,简言之也就是共享了同一个房间,JavaScript中就是同一块堆内存.
- 深复制:拷贝的是实例对象。因实例对象放在堆内存中的,要想实现深拷贝,必须重开辟一块堆内存,新创建原对象的实例,并保证不同的对象引用。使原对象与新建对象完全隔离互不影响。
1、浅复制【拷贝】
//数组浅复制
let arr=[1,2,3,5,8];
let item=[];
for(let i in arr){item[i]=arr[i];
}
item.push(9);
console.log('arr==>'+arr);//arr==>1,2,3,5,8
console.log('item==>'+item);//item==>1,2,3,5,8,9
//对象浅复制
let obj={name:'zjl',age:'28'};
let list={};
for(let i in obj){list[i]=obj[i];
}
list['like']='apple';
console.dir('obj===>'+JSON.stringify(obj));
console.dir('list===>'+JSON.stringify(list));obj===>{"name":"zjl","age":"28"}
list===>{"name":"zjl","age":"28","like":"apple"}
复制代码
以上例子可以看出,数组、对象实现了浅复制.但是上面的代码只能实现一层的拷贝,无法实现深层的拷贝,如果把上面的代码改动下,如下:
//对象浅复制
let obj={name:'zjl',age:'28'};
let list={};
for(let i in obj){list[i]=obj[i];
}
list['name']='lisi';
console.dir('obj===>'+JSON.stringify(obj));
console.dir('list===>'+JSON.stringify(list));obj===>{"name":"lisi","age":"28"}
list===>{"name":"lisi","age":"28"}
复制代码
上面的例子,可以看出对象name被改变了.影响了原始的对象值.因引用类型为地址传递,没有开辟新的堆内存,地址指向同一块内存位置,所以改变一个对象另一个对象也会随之改变。所以无法实现深层次的复制【拷贝】.怎样解决这个问题,我们需要使用深拷贝【复制】来完成,继续往下看...
2、深复制【拷贝】: 看下面的例子,递归实现深层复制:
var china = {nation: '中国',adrress: ['北京', '上海', '广州'],
}
//深复制,要想达到深复制就需要用递归
function deepCopy(o, c) {var c = c || {}for (var i in o) {if (typeof o[i] === 'object') { //要考虑深复制问题了if (o[i].constructor === Array) {//这是数组c[i] = []} else {//这是对象c[i] = {}}deepCopy(o[i], c[i])} else {c[i] = o[i]}}return c
}
var result = {}
result = deepCopy(china, result);
result.nation = '美国';
console.dir(JSON.stringify(result)); //{"adrress":["北京","上海","广州"],"nation":"美国"}
console.dir(JSON.stringify(china)); //{"adrress":["北京","上海","广州"],"nation":"中国"}
复制代码
从上面的例子,可以看出已经实现了,真正的复制.下面看下图解:
三、深复制【拷贝】方法还有很多种
深复制【拷贝】后,两个对象,包括其内部的元素互不干扰。
1、JSON.parse(JSON.stringify())反序列化
2、JQuery自带的,$.extend(true,{},obj);
3、loadsh.js的实现_.cloneDeep和_.clone(value, true)
复制代码
感兴趣的可以去了解下
鉴于有朋友评论对于JSON.parse(JSON.stringify())反序列化存在局限性,现在做以补充: 照旧,还是先看下例子: 1、对数组对象进行深层次的拷贝
let obj={
like:'color',
list:{item:['green','red']
}}let deepCopy = (JSON.parse(JSON.stringify(obj)));
deepCopy.list.item[0]='yellow';
console.log(deepCopy);//{like:'color',list:{item:['yellow','red']}
console.log(obj);//{like:'color',list:{item:['green','red']}
复制代码
2、针对undefined,function,symbol的拷贝
let obj={x: undefined, y: Object, z: Symbol("")};
console.log('序列化==>'+JSON.stringify(obj)); // 序列化==> '{}'
console.log('反序列化==>'+JSON.parse(JSON.stringify(obj))); // 反序列化==> {}
// 对应一个原型 __proto__let arr=[undefined, Object, Symbol("")];
console.log('序列化==>'+JSON.stringify(arr));
// 序列化==> '[null,null,null]'
console.log('反序列化 arr==>'+JSON.parse(JSON.stringify(arr)));
// 反序列化 arr==> [null,null,null]
// 反序列化 对应一个原型 __proto__复制代码
从以上实例得出以下结论:
undefined、任意的函数以及symbol值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)
复制代码
JSON.parse(JSON.stringify())虽不能对undefined,function,symbol进行深拷贝,但使用起来简单,可以满足大部分的场景,具体还是要根据需要选择使用.
JavaScript之闭包【三】
JavaScript之浅复制【拷贝】与深复制【拷贝】【二】相关推荐
- iOS 集合的深复制与浅复制
2019独角兽企业重金招聘Python工程师标准>>> 概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对 ...
- 也来谈一谈js的浅复制和深复制
2019独角兽企业重金招聘Python工程师标准>>> 1.浅复制VS深复制 本文中的复制也可以称为拷贝,在本文中认为复制和拷贝是相同的意思.另外,本文只讨论js中复杂数据类型的复制 ...
- [C++]深复制与浅复制
深复制与浅复制 C++中,默认的复制构造函数只能实现浅复制. 浅复制指的是在对象复制前,只对对象中的数据成员进行简单的复制 大多数情况下"浅复制"已经能很好的工作了,但是当类的数据 ...
- C++学习基础七——深复制与浅复制
C++学习基础七--深复制与浅复制 一.深复制与浅复制基本知识 深复制和浅复制,又称为深拷贝和浅拷贝. 深复制和浅复制的区别如下图1所示: 图1 图1表示的是,定义一个类CDemo,包含int a和c ...
- 深复制VS浅复制(MemberwiseClone方法介绍)
MemberwiseClone方法,属于命名空间System,存在于程序集 mscorlib.dll中.返回值是System.Object.其含义是:创建一个当前object对象的浅表副本. MSDN ...
- IOS学习笔记十八(copy、mutableCopy、NSCopying、NSMutableCopy、深复制、浅复制)
1. copy.mutableCopy方法 copy方法返回对象的不可修改的副本 mutableCopy方法返回的对象可修改的副本 1).测试demo int main(int argc, char ...
- 详解Python中的浅复制与深复制
列表对象的copy()方法返回列表的浅复制.所谓浅复制,是指生产一个新的列表,并且把原列表中所有元素的引用都复制到新列表中.如果原列表中只包含整数.实数.复数等基本类型或元组.字符串这样的不可变类型, ...
- SV学习笔记—浅复制和深复制的区别详解
目录 1.句柄的复制 2.对象的复制 2.1浅复制shallow copy 2.2深复制deep copy 3.this的用法 在类中,复制一半会涉及到句柄的复制,浅复制和深复制3种操作,下面来看看这 ...
- java clone(浅复制和深复制)的前世今生
之前只是听说clone,很高级的样子,一直没有用过,感觉日常开发好像用不到似的,谁知道这段时间的开发,发现clone非常好用,就专门学习了一下. 前世 先说说clone的由来吧,只知道它的用法,而不知 ...
最新文章
- 【科技】浅谈圆的反演
- android 关闭软键盘_HTC官方社区明天正式关闭,收入持续下滑或是直接原因
- springboot集成springDataJpa
- 虚拟机管理解决方案-VMware篇
- linux安装jdk环境
- Ubuntu系统下环境变量那些事儿
- 电脑端的mafsvr服务关掉_想在电脑上玩手游,你得试试这款 quot;同屏助手quot; 了...
- linux下录制视频流,Ubuntu Linux 下的PSP视频输出以及录制
- Vue3格式化Volar报错
- 西南大学计算机考研资料汇总
- android 实现微信分享
- MPU6050读取数据FIFO溢出问题
- chrome浏览器虚拟摄像头
- UIView和CALayer是啥关系
- HTTP协议及TCP分析
- IM即时通讯系统优势,区块链社交APP如何搭建
- (转载)深度工作:充分使用每一份脑力
- 数学分析与高等数学——学习资料(更新.........)
- adb命令查看app的日志
- Win10优化大师1.0 Beta 5发布,跟上微软的节奏