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 相关文章推荐
JQuery的read函数与js的onload不同方式实现
Mar 18 Javascript
根据身份证号自动输出相关信息(籍贯,出身日期,性别)
Nov 15 Javascript
jsPDF导出pdf示例
May 02 Javascript
jQuery实现文本框输入同步的方法
Jun 20 Javascript
JS面向对象编程详解
Mar 06 Javascript
JavaScript实现刷新不重记的倒计时
Aug 10 Javascript
AngularJS实现表格的增删改查(仅限前端)
Jul 04 Javascript
在vue项目中优雅的使用SVG的方法实例详解
Dec 03 Javascript
Angular中innerHTML标签的样式不起作用的原因解析
Jun 18 Javascript
微信小程序实现批量倒计时功能
Nov 01 Javascript
JavaScript日期库date-fn.js使用方法解析
Sep 09 Javascript
js删除指定位置超链接中含有百度与360的标题
Jan 06 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加速 eAccelerator配置和使用指南
2009/06/05 PHP
CentOS 6.2使用yum安装LAMP以及phpMyadmin详解
2013/06/17 PHP
php读取der格式证书乱码解决方法
2015/06/22 PHP
php商品对比功能代码分享
2015/09/24 PHP
PHP实现的一致性哈希算法完整实例
2015/11/14 PHP
laravel5.1框架基础之Blade模板继承简单使用方法分析
2019/09/05 PHP
实用的Jquery选项卡TAB示例代码
2013/08/28 Javascript
jquery滚动特效集锦
2015/06/03 Javascript
学习使用bootstrap的modal和carousel
2016/12/09 Javascript
js实现交通灯效果
2017/01/13 Javascript
Bootstrap table学习笔记(2) 前后端分页模糊查询
2017/05/18 Javascript
javascript 数据存储的常用函数总结
2017/06/01 Javascript
JS使用iView的Dropdown实现一个右键菜单
2019/05/06 Javascript
Layui点击图片弹框预览的实现方法
2019/09/16 Javascript
js实现带箭头的进度流程
2020/03/26 Javascript
微信小程序实现底部弹出框
2020/11/18 Javascript
[02:49]DOTA2完美大师赛首日观众采访
2017/11/23 DOTA
[04:46]2018年度玩家喜爱的电竞媒体-完美盛典
2018/12/16 DOTA
Python深入学习之特殊方法与多范式
2014/08/31 Python
使用Python的内建模块collections的教程
2015/04/28 Python
pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率
2020/01/02 Python
python数据预处理 :数据共线性处理详解
2020/02/24 Python
python pandas移动窗口函数rolling的用法
2020/02/29 Python
解决windows下python3使用multiprocessing.Pool出现的问题
2020/04/08 Python
matplotlib基础绘图命令之bar的使用方法
2020/08/13 Python
css3利用transform变形结合事件完成扇形导航
2020/10/26 HTML / CSS
使用HTML5拍照示例代码
2013/08/06 HTML / CSS
Booking.com西班牙:全球酒店预订
2018/03/30 全球购物
全球500多个机场的接送服务:Suntransfers
2019/06/03 全球购物
Derek Rose官网:英国高档睡衣、家居服和内衣品牌
2020/01/18 全球购物
应聘教师自荐书
2014/06/16 职场文书
机关党员进社区活动总结
2014/07/05 职场文书
科学发展观标语
2014/10/08 职场文书
上市公司董事长岗位职责
2015/04/16 职场文书
卫生院艾滋病宣传活动总结
2015/05/09 职场文书
python 中的@运算符使用
2021/05/26 Python