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 相关文章推荐
javascript同步Import,同步调用外部js的方法
Jul 08 Javascript
JavaScript作用域与作用域链深入解析
Dec 06 Javascript
jQuery实现字符串按指定长度加入特定内容的方法
Mar 11 Javascript
JQuery球队选择实例
May 18 Javascript
基于Bootstrap使用jQuery实现输入框组input-group的添加与删除
May 03 Javascript
jQuery中Ajax全局事件引用方式及各个事件(全局/局部)执行顺序
Jun 02 Javascript
Ionic2系列之使用DeepLinker实现指定页面URL
Nov 21 Javascript
学习vue.js中class与style绑定
Dec 03 Javascript
angularjs定时任务的设置与清除示例
Jun 02 Javascript
VUE实现可随意拖动的弹窗组件
Sep 25 Javascript
Vue Echarts实现可视化世界地图代码实例
May 07 Javascript
如何阻止小程序遮罩层下方图层滚动
Sep 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
DC游戏Steam周三特惠 《蝙蝠侠》阿卡姆系列平史低
2020/04/09 欧美动漫
php strtotime 函数UNIX时间戳
2009/01/14 PHP
基于MySQL体系结构的分析
2013/05/02 PHP
php array_keys 返回数组的键名
2016/10/25 PHP
php 多继承的几种常见实现方法示例
2019/11/18 PHP
通过Javascript创建一个选择文件的对话框代码
2012/06/16 Javascript
jQuery.validate 常用方法及需要注意的问题
2013/03/20 Javascript
ie下jquery.getJSON的缓存问题的处理方法
2013/03/29 Javascript
为Javascript中的String对象添加去除左右空格的方法(示例代码)
2013/11/30 Javascript
Javascript自定义函数判断网站访问类型是PC还是移动终端
2014/01/10 Javascript
js判断横竖屏及禁止浏览器滑动条示例
2014/04/29 Javascript
JS的encodeURI和java的URLDecoder.decode使用介绍
2014/05/08 Javascript
IE中JS跳转丢失referrer问题的2个解决方法
2014/07/18 Javascript
Node.js的包详细介绍
2015/01/14 Javascript
jQuery中Ajax的get、post等方法详解
2015/01/20 Javascript
javascript中日期函数new Date()的浏览器兼容性问题
2015/09/05 Javascript
Bootstrap组件(一)之菜单
2016/05/11 Javascript
一个可复用的vue分页组件
2017/05/15 Javascript
基于Vue的移动端图片裁剪组件功能
2017/11/28 Javascript
浏览器调试动态js脚本的方法(图解)
2018/01/19 Javascript
Vue使用vux-ui自定义表单验证遇到的问题及解决方法
2018/05/10 Javascript
Vue.JS实现垂直方向展开、收缩不定高度模块的JS组件
2018/06/19 Javascript
快速解决bootstrap下拉菜单无法隐藏的问题
2018/08/10 Javascript
Vue slot用法(小结)
2018/10/22 Javascript
Webpack4+Babel7+ES6兼容IE8的实现
2019/04/10 Javascript
深入理解redux之compose的具体应用
2020/01/12 Javascript
Python比较两个图片相似度的方法
2015/03/13 Python
用python 绘制茎叶图和复合饼图
2021/02/26 Python
web字体加载方案优化小结
2019/11/29 HTML / CSS
给交警的表扬信
2014/01/12 职场文书
烹饪大赛策划方案
2014/05/26 职场文书
征兵宣传标语
2014/06/20 职场文书
宾馆仓管员岗位职责
2014/07/27 职场文书
2014年科普工作总结
2014/12/06 职场文书
广播体操比赛主持词
2015/06/29 职场文书
2016年敬老月活动总结
2016/04/05 职场文书