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 attachEvent和addEventListener使用方法
Mar 19 Javascript
Jquery Ajax学习实例7 Ajax所有过程事件分析示例
Mar 23 Javascript
DD_belatedPNG,IE6下PNG透明解决方案(国外)
Dec 06 Javascript
zShowBox 图片放大展示jquery版 兼容性
Sep 24 Javascript
深入理解Vue.js源码之事件机制
Sep 27 Javascript
ActiveX控件的使用-js实现打印超市小票功能代码详解
Nov 22 Javascript
如何在js代码中消灭for循环实例详解
Jul 29 Javascript
VUE中v-on:click事件中获取当前dom元素的代码
Aug 22 Javascript
JS实现的类似微信聊天效果示例
Jan 29 Javascript
vue.js中ref和$refs的使用及示例讲解
Aug 14 Javascript
vue中对象数组去重的实现
Feb 06 Javascript
vue 自定指令生成uuid滚动监听达到tab表格吸顶效果的代码
Sep 16 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 内存缓存加速功能memcached安装与用法
2009/09/03 PHP
PHP使用 Pear 进行安装和卸载包的方法详解
2019/07/08 PHP
图片自动更新(说明)
2006/10/02 Javascript
Web层改进II-用xmlhttp 无声息提交复杂表单
2007/01/22 Javascript
利用Dojo和JSON建立无限级AJAX动态加载的功能模块树
2007/03/24 Javascript
使用js检测浏览器的实现代码
2013/05/14 Javascript
jquery链式操作的正确使用方法
2014/01/06 Javascript
JS实现判断碰撞的方法
2015/02/11 Javascript
nodejs实现获取某宝商品分类
2015/05/28 NodeJs
jquery实现九宫格大转盘抽奖
2015/11/13 Javascript
js操作数组函数实例小结
2015/12/10 Javascript
基于jQuery的AJAX和JSON实现纯html数据模板
2016/08/09 Javascript
详解小程序输入框闪烁及重影BUG解决方案
2018/08/31 Javascript
浅谈vue 锚点指令v-anchor的使用
2019/11/13 Javascript
JS判断浏览器类型与操作系统的方法分析
2020/04/30 Javascript
python安装oracle扩展及数据库连接方法
2017/02/21 Python
Python基于列表list实现的CRUD操作功能示例
2018/01/05 Python
python删除字符串中指定字符的方法
2018/08/13 Python
Pandas之MultiIndex对象的示例详解
2019/06/25 Python
对python中url参数编码与解码的实例详解
2019/07/25 Python
Python中的延迟绑定原理详解
2019/10/11 Python
Python selenium的基本使用方法分析
2019/12/21 Python
Python基于正则表达式实现计算器功能
2020/07/13 Python
详解python方法之绑定方法与非绑定方法
2020/08/17 Python
布鲁明戴尔百货店:Bloomingdale’s
2016/12/21 全球购物
匡威荷兰官方网站:Converse荷兰
2018/10/24 全球购物
不开辟用于交换数据的临时空间,如何完成字符串的逆序
2012/12/02 面试题
家长给孩子的表扬信
2014/01/17 职场文书
决心书范文
2014/03/11 职场文书
党政领导班子四风问题对照检查材料思想汇报
2014/10/02 职场文书
团员年度个人总结
2015/02/26 职场文书
2016年党员创先争优承诺书
2016/03/25 职场文书
pandas:get_dummies()与pd.factorize()的用法及区别说明
2021/05/21 Python
Tomcat用户管理的优化配置详解
2022/03/31 Servers
python 单机五子棋对战游戏
2022/04/28 Python
Win10系统搭建ftp文件服务器详细教程
2022/08/05 Servers