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 相关文章推荐
在JavaScript中使用inline函数的问题
Mar 08 Javascript
jQuery 源码分析笔记(6) jQuery.data
Jun 08 Javascript
JQuery判断子iframe何时加载完成解决方案
Aug 20 Javascript
使用JavaScript链式编程实现模拟Jquery函数
Dec 21 Javascript
jQuery手机拨号界面特效代码分享
Aug 27 Javascript
D3.js实现柱状图的方法详解
Sep 21 Javascript
@ResponseBody 和 @RequestBody 注解的区别
Mar 08 Javascript
详解在express站点中使用ejs模板引擎
Sep 21 Javascript
Vue-router路由判断页面未登录跳转到登录页面的实例
Oct 26 Javascript
微信小程序实现图片预览功能
Jan 31 Javascript
vue利用v-for嵌套输出多层对象,分别输出到个表的方法
Sep 07 Javascript
微信小程序实现上传多个文件 超过10个
Mar 30 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
用Flash图形化数据(一)
2006/10/09 PHP
一个图形显示IP的PHP程序代码
2007/10/19 PHP
实用函数7
2007/11/08 PHP
php在线代理转向代码
2012/05/05 PHP
php调用shell的方法
2014/11/05 PHP
php微信高级接口群发 多客服
2016/06/23 PHP
php好代码风格的阶段性总结
2016/06/25 PHP
PHP的JSON封装、转变及输出操作示例
2019/09/27 PHP
Laravel 自定命令以及生成文件的例子
2019/10/23 PHP
PHP时间类完整代码实例
2021/02/26 PHP
转义字符(\)对JavaScript中JSON.parse的影响概述
2013/07/17 Javascript
JavaScript对数字的判断与处理实例分析
2015/02/02 Javascript
jQuery支持添加事件的日历特效代码分享(3种样式)
2015/08/24 Javascript
JavaScript获取浏览器信息的方法
2015/11/20 Javascript
PHP 实现一种多文件上传的方法
2017/09/20 Javascript
JS实现的tab页切换效果完整示例
2018/12/18 Javascript
微信小程序-API接口安全详解
2019/07/16 Javascript
swiper Scrollbar滚动条组件详解
2019/09/08 Javascript
JavaScript设计模式--简单工厂模式定义与应用案例详解
2020/05/23 Javascript
javascript实现京东登录显示隐藏密码
2020/08/02 Javascript
JavaScript中如何调用Java方法
2020/09/16 Javascript
详细介绍Python中的偏函数
2015/04/27 Python
详解详解Python中writelines()方法的使用
2015/05/25 Python
深入解析Python中的__builtins__内建对象
2016/06/21 Python
Python基于QRCode实现生成二维码的方法【下载,安装,调用等】
2017/07/11 Python
用python实现刷点击率的示例代码
2019/02/21 Python
浅析PEP572: 海象运算符
2019/10/15 Python
法国高保真音响和家庭影院商店:Son Video
2019/04/26 全球购物
名词解释型面试题(主要是网络)
2013/12/27 面试题
当x.equals(y)等于true时,x.hashCode()与y.hashCode()可以不相等,这句话对不对
2015/05/02 面试题
助人为乐好少年事迹材料
2014/08/18 职场文书
房屋出租委托书格式
2014/09/23 职场文书
2014年学校党建工作汇报材料
2014/11/02 职场文书
2014年体育工作总结
2014/11/24 职场文书
关于html选择框创建占位符的问题
2021/06/09 HTML / CSS
Python中的 Set 与 dict
2022/03/13 Python