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 相关文章推荐
用cookies实现的可记忆的样式切换效果代码下载
Dec 24 Javascript
js 新浪的一个图片播放图片轮换效果代码
Jul 15 Javascript
浅谈JavaScript中的Math.atan()方法的使用
Jun 14 Javascript
javascript实现选中复选框后相关输入框变灰不可用的方法
Aug 11 Javascript
基于bootstrap插件实现autocomplete自动完成表单
May 07 Javascript
jQuery 获取多选框的值及多选框中文的函数
May 16 Javascript
详解Vue路由开启keep-alive时的注意点
Jun 20 Javascript
详解微信小程序设置底部导航栏目方法
Jun 29 Javascript
js 提取某()特殊字符串长度的实例
Dec 06 Javascript
原生js实现淘宝放大镜效果
Oct 28 Javascript
jQuery实现checkbox全选、反选及删除等操作的方法详解
Aug 02 jQuery
使用Cargo工具高效创建Rust项目
Aug 14 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中的session永不过期的解决思路及实现方法分享
2011/04/20 PHP
php显示指定目录下子目录的方法
2015/03/20 PHP
PHP实现截取中文字符串不出现?号的解决方法
2016/12/29 PHP
PHP实现可添加水印与生成缩略图的图片处理工具类
2018/01/16 PHP
动态加载图片路径 保持JavaScript控件的相对独立性
2010/09/03 Javascript
jquery调用wcf并展示出数据的方法
2011/07/07 Javascript
JS Pro-深入面向对象的程序设计之继承的详解
2013/05/07 Javascript
javascript内置对象操作详解
2015/02/04 Javascript
Javascript 闭包详解及实例代码
2016/11/30 Javascript
js中document.referrer实现移动端返回上一页
2017/02/22 Javascript
node实现定时发送邮件的示例代码
2017/08/26 Javascript
node.js学习之断言assert的使用示例
2017/09/28 Javascript
Es6 Generator函数详细解析
2018/02/24 Javascript
基于vue 添加axios组件,解决post传参数为null的问题
2018/03/05 Javascript
Javascript实现异步编程的过程
2018/06/18 Javascript
echarts同一页面中四个图表切换的js数据交互方法示例
2018/07/03 Javascript
Vue 中axios配置实例详解
2018/07/27 Javascript
Vue实现调节窗口大小时触发事件动态调节更新组件尺寸的方法
2018/09/15 Javascript
node使用Mongoose类库实现简单的增删改查
2018/11/08 Javascript
ES6 Promise对象的含义和基本用法分析
2019/06/14 Javascript
NProgress显示顶部进度条效果及使用详解
2019/09/21 Javascript
在vue项目中promise解决回调地狱和并发请求的问题
2020/11/09 Javascript
python读取文本绘制动态速度曲线
2018/06/21 Python
python单例设计模式实现解析
2020/01/07 Python
python数据预处理 :数据共线性处理详解
2020/02/24 Python
Python简单实现词云图代码及步骤解析
2020/06/04 Python
详解pycharm连接远程linux服务器的虚拟环境的方法
2020/11/13 Python
利用HTML5的新特点实现图片文件异步上传
2014/05/29 HTML / CSS
新加坡最受追捧的体验平台:Hapz
2018/01/01 全球购物
大学生职业规划前言模板
2013/12/27 职场文书
英语专业学生的自我评价
2013/12/30 职场文书
2014年小学教学工作总结
2014/11/13 职场文书
保研推荐信格式
2015/03/25 职场文书
基层工作经历证明
2015/06/19 职场文书
重阳节活动主持词
2015/07/04 职场文书
爱护公物主题班会
2015/08/17 职场文书