下面了解下什么浅复制【拷贝】和深复制【拷贝】,通过下面的阅读你将了解到:

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之浅复制【拷贝】与深复制【拷贝】【二】相关推荐

  1. iOS 集合的深复制与浅复制

    2019独角兽企业重金招聘Python工程师标准>>> 概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对 ...

  2. 也来谈一谈js的浅复制和深复制

    2019独角兽企业重金招聘Python工程师标准>>> 1.浅复制VS深复制 本文中的复制也可以称为拷贝,在本文中认为复制和拷贝是相同的意思.另外,本文只讨论js中复杂数据类型的复制 ...

  3. [C++]深复制与浅复制

    深复制与浅复制 C++中,默认的复制构造函数只能实现浅复制. 浅复制指的是在对象复制前,只对对象中的数据成员进行简单的复制 大多数情况下"浅复制"已经能很好的工作了,但是当类的数据 ...

  4. C++学习基础七——深复制与浅复制

    C++学习基础七--深复制与浅复制 一.深复制与浅复制基本知识 深复制和浅复制,又称为深拷贝和浅拷贝. 深复制和浅复制的区别如下图1所示: 图1 图1表示的是,定义一个类CDemo,包含int a和c ...

  5. 深复制VS浅复制(MemberwiseClone方法介绍)

    MemberwiseClone方法,属于命名空间System,存在于程序集 mscorlib.dll中.返回值是System.Object.其含义是:创建一个当前object对象的浅表副本. MSDN ...

  6. IOS学习笔记十八(copy、mutableCopy、NSCopying、NSMutableCopy、深复制、浅复制)

    1. copy.mutableCopy方法 copy方法返回对象的不可修改的副本 mutableCopy方法返回的对象可修改的副本 1).测试demo int main(int argc, char ...

  7. 详解Python中的浅复制与深复制

    列表对象的copy()方法返回列表的浅复制.所谓浅复制,是指生产一个新的列表,并且把原列表中所有元素的引用都复制到新列表中.如果原列表中只包含整数.实数.复数等基本类型或元组.字符串这样的不可变类型, ...

  8. SV学习笔记—浅复制和深复制的区别详解

    目录 1.句柄的复制 2.对象的复制 2.1浅复制shallow copy 2.2深复制deep copy 3.this的用法 在类中,复制一半会涉及到句柄的复制,浅复制和深复制3种操作,下面来看看这 ...

  9. java clone(浅复制和深复制)的前世今生

    之前只是听说clone,很高级的样子,一直没有用过,感觉日常开发好像用不到似的,谁知道这段时间的开发,发现clone非常好用,就专门学习了一下. 前世 先说说clone的由来吧,只知道它的用法,而不知 ...

最新文章

  1. 【科技】浅谈圆的反演
  2. android 关闭软键盘_HTC官方社区明天正式关闭,收入持续下滑或是直接原因
  3. springboot集成springDataJpa
  4. 虚拟机管理解决方案-VMware篇
  5. linux安装jdk环境
  6. Ubuntu系统下环境变量那些事儿
  7. 电脑端的mafsvr服务关掉_想在电脑上玩手游,你得试试这款 quot;同屏助手quot; 了...
  8. linux下录制视频流,Ubuntu Linux 下的PSP视频输出以及录制
  9. Vue3格式化Volar报错
  10. 西南大学计算机考研资料汇总
  11. android 实现微信分享
  12. MPU6050读取数据FIFO溢出问题
  13. chrome浏览器虚拟摄像头
  14. UIView和CALayer是啥关系
  15. HTTP协议及TCP分析
  16. IM即时通讯系统优势,区块链社交APP如何搭建
  17. (转载)深度工作:充分使用每一份脑力
  18. 数学分析与高等数学——学习资料(更新.........)
  19. adb命令查看app的日志
  20. Win10优化大师1.0 Beta 5发布,跟上微软的节奏

热门文章

  1. Rails 新浪微博的登录认证
  2. 【工具篇】抓包中的王牌工具—Fiddler (1-环境搭建)
  3. Django自带的加密算法及加密模块
  4. BZOJ1084 SCOI2005最大子矩阵
  5. 二分图-匈牙利算法模板
  6. mac 系统下nvm管理node安装遇到的问题
  7. ios开发之UIView的frame、bounds跟center属性的区别(附图)
  8. zoj 2760 How Many Shortest Path 最大流
  9. opencv实现图片HDR功能
  10. Ubuntu下安装Nginx,PHP5(及PHP-FPM),MySQL