js实现数组和对象的深浅拷贝


Posted in Javascript onSeptember 30, 2017

前提:原始数据类型和对象类型赋值时的差异

JavaScript的数据类型分为原始数据类型和对象类型。二者在内存中存放的方式不同,导致了其赋值时差异。分别举个栗子

var x = 1;
 var y = x; //y获得了和x同样的值
 y = 2;
 console.log(x); // 1

 var m = [1,2]; //m存放的是指向[1,2]这个数组对象的引用地址
 var n = m; //n也获得 [1,2]数组对象的引用地址
 n[0] = 3;
 console.log(m); //[3,2]

由上栗子可以看出 :原始数据类型赋值时,给的是实实在在的数据值 ,赋值后二者只是值一样而已,不会相互影响; 而对象类型,给的是 原数据的引用地址,所以新旧数据会互相影响,因为本质上还是同一个数据对象,如上栗中的数组 

什么是浅拷贝?

顾名思义,浅拷贝就是流于表面的拷贝方式;当属性值为对象类型时,只拷贝了对象数据的引用,导致新旧数据没有完全分离,还会互相影响。再举个栗子···

//测试数据
var array1 = ['a',1,true,{name:'lei',age:18}];
 
//concat() slice() 实现浅拷贝
var array2 = array1.concat()
 
//修改拷贝后的数据
array2[0] = 'b';      //array1[0]是原始数据类型 所以是直接赋值的
array2[3].name = 'zhang';  //array1[3]是对象数据类型 所以拷贝的是对象的引用,其实还是和原数组使用同一对象
 
console.log(array1);  // ['a',1,true,{name:'zhang',age:18}]

栗子中 array2是array1的浅拷贝对象,数组元素是原始数据类型的不会相互影响了(array1[0]),但是array1[3]是对象类型,还是会互相影响。

如何实现浅拷贝

上栗中的  array.concat()或者array.slice() 是特殊的实现数组浅拷贝的方式。

如何自己实现呢?遍历对象/数组的每个属性,然后赋值给一个新的对象不就行了么,如下实现

//实现浅拷贝
 function shallowCopy( target ){
  if(typeof target !== 'object') return ;
  //判断目标类型,来创建返回值
  var newObj = target instanceof Array ? [] : {};
 
  for(var item in target){
   //只复制元素自身的属性,不复制原型链上的
   if(target.hasOwnProperty(item)){
    newObj[item] = target[item]
   }
  }
 
  return newObj
 }</strong>
 
 //测试
 
 var test = [1,'a',{name:'lei',age:18}];
 
 var copy = shallowCopy(test);
 console.log(copy[2].name);  //lei
 
 copy[2].name = 'zhang';
 console.log(test[2].name);  //zhang  原数据也被修改

深拷贝及其实现

从浅拷贝解释基本可以明白,深拷贝就是 ‘完全'拷贝,拷贝之后新旧数据完全分离,不再共用对象类型的属性值,不会互相影响。

实现方式:

取巧方式 JSON.parse(JSON.stringify(Obj))  

var test = [1,'a',{name:'lei',age:18}]; 
var copy1 = JSON.parse(JSON.stringify(test)); //特殊方式 
console.log(copy1); 
copy1[2].name = 'zhang'
console.log(test);  //[1,'a',{name:'lei',age:18}] 未受到影响

注意:这种方式不能深拷贝有属性值为函数的对象,  可自行尝试

2. 实现深拷贝

    已经实现了浅拷贝,思考下应该是对 对象类型属性值赋值时,导致的没有完全分离,所以要修改下 拷贝对象类型属性值的方式,对它再调用一次深拷贝,这样就实现了深拷贝,如下:

//实现深拷贝
function deepCopy( target ){
 if(typeof target !== 'object') return ;
 //判断目标类型,来创建返回值
 var newObj = target instanceof Array ? [] : {};
 
 for(var item in target){
  //只复制元素自身的属性,不复制原型链上的
  if(target.hasOwnProperty(item)){
   newObj[item] = <strong>typeof target[item] == 'object' ? deepCopy(target[item]) : target[item] //判断属性值类型
</strong>  }
 }
 
 return newObj
}
 
//测试
var test = [1,'a',{name:'lei',age:18}];
 
var copy2 = deepCopy(test);
copy2[2].name = 'zhang'
 
console.log(test); ////[1,'a',{name:'lei',age:18}] 未受到影响

总结

一定要理解造成浅拷贝的原因:对象类型数据复制时,复制了引用地址,用的还是同一个数据对象;所以实现深拷贝的方式就是要对 对象类型属性值递归进行深拷贝,避免直接赋值。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
iframe 自适应高度[在IE6 IE7 FF下测试通过]
Apr 13 Javascript
JS小功能(onmouseover实现选择月份)实例代码
Nov 28 Javascript
浅析offsetLeft,Left,clientLeft之间的区别
Nov 30 Javascript
基于JQuery实现的Select级联
Jan 27 Javascript
Jquery弹出层插件ThickBox的使用方法
Dec 09 Javascript
JavaScript必知必会(三) String .的方法来自何方
Jun 08 Javascript
jQuery密码强度验证控件使用详解
Jan 05 Javascript
详解利用 Express 托管静态文件的方法
Sep 18 Javascript
基于Vue 2.0的模块化前端 UI 组件库小结
Dec 21 Javascript
JS实现标签滚动切换效果
Dec 25 Javascript
微信小程序动态生成二维码的实现代码
Jul 25 Javascript
深入理解Puppeteer的入门教程和实践
Mar 05 Javascript
node通过express搭建自己的服务器
Sep 30 #Javascript
react-native中ListView组件点击跳转的方法示例
Sep 30 #Javascript
详解在Vue中有条件地使用CSS类
Sep 30 #Javascript
react-native组件中NavigatorIOS和ListView结合使用的方法
Sep 30 #Javascript
vue按需引入element Transfer 穿梭框
Sep 30 #Javascript
vue获取DOM元素并设置属性的两种实现方法
Sep 30 #Javascript
jQuery完成表单验证的实例代码(纯代码)
Sep 30 #jQuery
You might like
组合算法的PHP解答方法
2012/02/04 PHP
理解PHP中的stdClass类
2014/04/18 PHP
ThinkPHP里用U方法调用js文件实例
2015/06/18 PHP
laravel5.6 框架操作数据 Eloquent ORM用法示例
2020/01/26 PHP
用javascript获取当页面上鼠标光标位置和触发事件的对象的代码
2009/12/09 Javascript
在VS2008中使用jQuery智能感应的方法
2010/12/30 Javascript
JavaScript的Module模式编程深入分析
2013/08/13 Javascript
javascript函数自动执行常用方法汇总
2016/03/28 Javascript
JavaScript仿淘宝页面图片滚动加载及刷新回顶部的方法解析
2016/05/24 Javascript
js将字符串中的每一个单词的首字母变为大写其余均为小写
2017/01/05 Javascript
详解NODEJS基于FFMPEG视频推流测试
2017/11/17 NodeJs
详解ES6 Fetch API HTTP请求实用指南
2018/11/14 Javascript
javascript单张多张图无缝滚动实例代码
2020/05/10 Javascript
[01:01:14]完美世界DOTA2联赛PWL S2 SZ vs Rebirth 第一场 11.21
2020/11/23 DOTA
用pandas按列合并两个文件的实例
2018/04/12 Python
Python实现对文件进行单词划分并去重排序操作示例
2018/07/10 Python
利用pyshp包给shapefile文件添加字段的实例
2019/12/06 Python
python多维数组分位数的求取方式
2020/03/03 Python
基于python实现复制文件并重命名
2020/09/16 Python
Pandas对每个分组应用apply函数的实现
2020/12/13 Python
html5基础标签(html5视频标签 html5新标签用法)
2013/12/30 HTML / CSS
详解如何解决canvas图片getImageData,toDataURL跨域问题
2018/09/17 HTML / CSS
匡威比利时官网:Converse Belgium
2017/04/13 全球购物
巴西女装购物网站:Eclectic
2018/04/24 全球购物
伦敦剧院门票:London Theatre Direct
2018/11/21 全球购物
如果一个类实现了多个接口但是这些接口有相同的方法名将会怎样
2013/06/16 面试题
母亲节感恩活动记录
2014/03/16 职场文书
国旗下演讲稿
2014/05/08 职场文书
平安建设工作方案
2014/06/02 职场文书
小学兴趣小组活动总结
2014/07/07 职场文书
解放思想演讲稿
2014/09/11 职场文书
2014党委书记四风问题对照检查材料思想汇报
2014/09/22 职场文书
保护环境的宣传语
2015/07/13 职场文书
php字符串倒叙
2021/04/01 PHP
Python批量将csv文件转化成xml文件的实例
2021/05/10 Python
pandas 实现将NaN转换为None
2021/05/14 Python