JS中的两种数据类型及实现引用类型的深拷贝的方法


Posted in Javascript onAugust 12, 2018

一.前言

我们知道,在JS中数据类型按照访问方式和存储方式的不同可分为基本类型和引用类型。

基本类型

基本类型有String、Boolean、Number,Undefined、Null,这些基本类型都是按值传递的,也称为值类型。

引用类型

引用类型有对象、数组、函数,它们都是按引用访问的。

二.存储方式区别

基本类型和引用类型由于两者在内存中存储的方式不同,造成两者访问的方式也不同。其中,基本类型存储在内存的栈中,是按值访问;引用类型存储在内存的堆中,是按引用访问。可如下图所示:

当有

var n1 = 10;
 var n2 = 10;
 var arr1 = [1,2,3,4]
 var arr2 = [1,2,3,4]

其在内存中存储方式如图:

JS中的两种数据类型及实现引用类型的深拷贝的方法

值类型是在栈中直接保存的变量的实际值,而引用类型在栈中仅仅保存的是变量指向堆中的地址,从上图中可以看出,值类型的变量n1和n2都是10,但是在栈中却为这两个变量分别开辟了两块空间来存储,而引用类型的变量arr1和arr2也相同,但是在堆中仅仅开辟了一块内存来存储,而在栈中存储的是这两个变量指向堆中的地址,这两个变量都指向堆中的同一片地址。

三.拷贝区别

正是由于两者在存储方式上的不同,造成了两者在拷贝时的差异。首先,先看两段代码:

var n1 = 10;
 //将n1拷贝给n2
 var n2 = n1;
 n1 = 12;
 console.log(n1);
 console.log(n2);

先定义变量n1=10,然后将n1拷贝给n2,再接着改变n1的值为12,分别打印n1和n2的值,打印结果为:

JS中的两种数据类型及实现引用类型的深拷贝的方法

从结果中我们可以看到,n1变为12了,但是n2不受影响,依旧是10。

再看另外一段代码:

var arr1 = [1,2,3,4]
 //将arr1拷贝给arr2
 var arr2 = arr1;
 //向arr1中尾部添加一个元素5
 arr1.push(5); 
 console.log(arr1);
 console.log(arr2);

先定义数组arr1,然后将arr1拷贝给arr2,再接着向arr1中尾部追加一个元素,分别打印arr1和arr2的值,打印结果为:

JS中的两种数据类型及实现引用类型的深拷贝的方法

从结果中我们可以看到:我们先将arr1拷贝给了arr2,但是当我们改变arr1时,arr2也跟着一起改变了。这印证了前文所说的,arr1和arr2实际上是指向了内存中的同一片地址,当arr1发生变化时,实际上是将指向的这片内存地址中的数据变化了,而arr2也指向的是这片地址,所以arr2也会跟着变化。

上面代码中的arr2=arr1,就是我们俗称的浅拷贝,浅拷贝仅仅拷贝的是变量名,其在内存的存储没有被拷贝,指向的还是同一片内存地址,这就是造成了一个变化另外一个也跟着变化,这在日常开发中不是我们想要的。

那如何实现真正的拷贝呢?

四.实现深拷贝

真正的拷贝,就是拷贝过后,arr1和arr2指向的不再是同一片内存地址,而是分别指向各自的地址,这样发生变化的时候就不会出现同时变化,这就是深拷贝。

下面我们封装一个深拷贝函数,来实现引用类型的深拷贝:

//参数p为原对象
 //参数c为原对象的类型,若原对象为数组,则传入c为[],若原对象是对象传入c为{},也可不传默认为{}
 function deepCopy(p,c){
 var c = c || {};
 for(var i in p){
 if(typeof p[i] === "object"){
 

c[i] = (p[i].constructor === Array)?[]:{};
 

deepCopy(p[i],c[i])
 

}else{
 

c[i] = p[i]

  }
 
}
 
return c;
 }

五.测试

//参数p为原对象
 //参数c为原对象的类型,若原对象为数组,则传入c为[],若原对象是对象传入c为{},也可不传默认为{}
 function deepCopy(p,c){
 var c = c || {};
 for(var i in p){
 if(typeof p[i] === "object"){
 

 c[i] = (p[i].constructor === Array)?[]:{};
 

 deepCopy(p[i],c[i])
 

}else{
 


c[i] = p[i]
 

}
 
}
 
return c;
 }
 //定义数组arr1
 var arr1 = [1,2,3,4]
 //将arr1拷贝给arr2
 var arr2 = deepCopy(arr1,[]);
 //向arr1中尾部添加一个元素5
 arr1.push(5);
 console.log('arr1:',arr1);
 console.log('arr2:',arr2);

测试结果:

JS中的两种数据类型及实现引用类型的深拷贝的方法

结果中可以看到,arr1变化没有引起arr2的变化,实现了真正的拷贝。

总结

以上所述是小编给大家介绍的JS中的两种数据类型及实现引用类型的深拷贝的方法,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
纯JS实现动态时间显示代码
Feb 08 Javascript
JS实现简单的图书馆享元模式实例
Jun 30 Javascript
jQuery插件Timelinr 实现时间轴特效
Oct 04 Javascript
跟我学习javascript的定时器
Nov 19 Javascript
JavaScript类型系统之基本数据类型与包装类型
Jan 06 Javascript
详解能在多种前端框架下使用的表格控件
Jan 11 Javascript
详解angularjs实现echart图表效果最简洁教程
Nov 29 Javascript
vue动态删除从数据库倒入列表的某一条方法
Sep 29 Javascript
vue elementUI table表格数据 滚动懒加载的实现方法
Apr 04 Javascript
Vue2.0实现组件之间数据交互和通信操作示例
May 16 Javascript
js找出5个数中最大的一个数和倒数第二大的数实现方法示例小结
Mar 04 Javascript
《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析
Apr 07 Javascript
原生JS封装_new函数实现new关键字的功能
Aug 12 #Javascript
axios向后台传递数组作为参数的方法
Aug 11 #Javascript
让axios发送表单请求形式的键值对post数据的实例
Aug 11 #Javascript
axios的拦截请求与响应方法
Aug 11 #Javascript
解决axios发送post请求返回400状态码的问题
Aug 11 #Javascript
vue 组件的封装之基于axios的ajax请求方法
Aug 11 #Javascript
解决Vue axios post请求,后台获取不到数据的问题方法
Aug 11 #Javascript
You might like
浅谈PHP Cookie处理函数
2016/06/10 PHP
php中10个不同等级压缩优化图片操作示例
2016/11/14 PHP
PHP创建文件及写入数据(覆盖写入,追加写入)的方法详解
2019/02/15 PHP
php项目中类的自动加载实例讲解
2019/09/12 PHP
在TP5数据库中四个字段实现无限分类的示例
2019/10/18 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
2020/02/21 PHP
Javascript实例教程(19) 使用HoTMetal(3)
2006/12/23 Javascript
二行代码解决全部网页木马
2008/03/28 Javascript
JavaScript日历实现代码
2010/09/12 Javascript
js中页面的重新加载(当前页面/上级页面)及frame或iframe元素引用介绍
2013/01/24 Javascript
THREE.JS入门教程(6)创建自己的全景图实现步骤
2013/01/25 Javascript
js调用AJAX时Get和post的乱码解决方法
2013/06/04 Javascript
jQuery+css实现百度百科的页面导航效果
2014/12/16 Javascript
前端框架Vue.js中Directive知识详解
2016/09/12 Javascript
详解Angular调试技巧之报错404(not found)
2018/01/31 Javascript
利用原生的JavaScript实现简单拼图游戏
2018/11/18 Javascript
Node.js 深度调试方法解析
2020/07/28 Javascript
vue实现两个区域滚动条同步滚动
2020/12/13 Vue.js
[52:57]2014 DOTA2国际邀请赛中国区预选赛 LGD-CDEC VS HGT
2014/05/21 DOTA
[01:24:34]2014 DOTA2华西杯精英邀请赛5 24 DK VS LGD
2014/05/25 DOTA
python2.6.6如何升级到python2.7.14
2018/04/08 Python
python读取中文txt文本的方法
2018/04/12 Python
使用Python opencv实现视频与图片的相互转换
2019/07/08 Python
利用matplotlib为图片上添加触发事件进行交互
2020/04/23 Python
Python如何设置指定窗口为前台活动窗口
2020/08/12 Python
Pycharm连接gitlab实现过程图解
2020/09/01 Python
Html5+CSS3+EL表达式问题小结
2020/12/19 HTML / CSS
Room Mate Hotels美国:西班牙酒店品牌
2018/04/10 全球购物
军训自我鉴定
2013/12/14 职场文书
中学运动会广播稿
2014/01/19 职场文书
移风易俗倡议书
2014/04/15 职场文书
校园安全标语
2014/06/07 职场文书
少先队活动总结
2014/08/29 职场文书
讲文明懂礼貌演讲稿
2014/09/11 职场文书
出差报告格式模板
2014/11/06 职场文书
2014年管理工作总结
2014/11/22 职场文书