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 相关文章推荐
几种延迟加载JS代码的方法加快网页的访问速度
Oct 12 Javascript
jquery checkbox实现单选小例
Nov 27 Javascript
JS字符串拼接在ie中都报错的解决方法
Mar 27 Javascript
JQuery each()嵌套使用小结
Apr 18 Javascript
jQuery学习笔记之jQuery原型属性和方法
Jun 09 Javascript
JavaScript 实现的 zip 压缩和解压缩工具包Zip.js使用详解
Dec 14 Javascript
纯JS实现图片验证码功能并兼容IE6-8(推荐)
Apr 19 Javascript
微信小程序实现的贪吃蛇游戏【附源码下载】
Jan 03 Javascript
解析Json字符串的三种方法日常常用
May 02 Javascript
对于防止按钮重复点击的尝试详解
Apr 22 Javascript
微信小程序自定义支持图片的弹窗
Dec 21 Javascript
Promise静态四兄弟实现示例详解
Jul 07 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面向对象全攻略 (三)特殊的引用“$this”的使用
2009/09/30 PHP
php smarty截取中文字符乱码问题?gb2312/utf-8
2011/11/07 PHP
php 强制下载文件实现代码
2013/10/28 PHP
php中的路径问题与set_include_path使用介绍
2014/02/11 PHP
php简单实现查询数据库返回json数据
2015/04/16 PHP
修改PHP脚本使WordPress拦截垃圾评论的方法示例
2015/12/10 PHP
PHP之图片上传类实例代码(加了缩略图)
2016/06/30 PHP
php代码调试利器firephp安装与使用方法分析
2018/08/21 PHP
一个可以兼容IE FF的加为首页与加入收藏实现代码
2009/11/02 Javascript
JS模拟自动点击的简单实例
2013/08/08 Javascript
用jquery仿做发微博功能示例
2014/04/18 Javascript
jQuery中:submit选择器用法实例
2015/01/03 Javascript
JS简单计算器实例
2015/01/20 Javascript
JS判断鼠标进入容器的方向与window.open新窗口被拦截的问题
2016/12/23 Javascript
详解Angular-Cli中引用第三方库
2017/05/21 Javascript
React中的refs的使用教程
2018/02/13 Javascript
详解Immutable及 React 中实践
2018/03/01 Javascript
微信小程序云开发修改云数据库中的数据方法
2019/05/18 Javascript
Object.keys() 和 Object.getOwnPropertyNames() 的区别详解
2020/05/21 Javascript
[51:43]OG vs LGD 2018国际邀请赛淘汰赛BO3 第五场 8.26
2018/08/30 DOTA
Ubuntu下安装PyV8
2016/03/13 Python
pip安装提示Twisted错误问题(Python3.6.4安装Twisted错误)
2020/05/09 Python
Python tempfile模块生成临时文件和临时目录
2020/09/30 Python
浅谈HTML5新增和废弃的标签
2019/04/28 HTML / CSS
营销与策划个人求职信
2013/09/22 职场文书
学术会议欢迎词
2014/01/09 职场文书
大学竞选班长演讲稿
2014/04/24 职场文书
二年级班级文化建设方案
2014/05/10 职场文书
关于责任的演讲稿
2014/05/20 职场文书
社区志愿者培训方案
2014/06/10 职场文书
员工年度工作总结2015
2015/05/18 职场文书
初中军训感言
2015/08/01 职场文书
卖车协议书范文
2016/03/23 职场文书
Memcached介绍及php-memcache扩展安装
2021/04/01 PHP
Lombok的详细使用及优缺点总结
2021/07/15 Java/Android
一文搞懂Python Sklearn库使用
2021/08/23 Python