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 相关文章推荐
用倒置滤镜把div倒置,再把table倒置。
Jul 31 Javascript
jquery 简短几句代码实现给元素动态添加及获取提示信息
Sep 01 Javascript
javascript之典型高阶函数应用介绍
Jan 10 Javascript
javascript中this的四种用法
May 11 Javascript
基于Vuejs实现购物车功能
Aug 02 Javascript
使用微信小程序开发前端【快速入门】
Dec 05 Javascript
JSON字符串和JSON对象相互转化实例详解
Jan 05 Javascript
微信小程序  http请求封装详解及实例代码
Feb 15 Javascript
js实现二级菜单点击显示当前内容效果
Apr 28 Javascript
Vue绑定内联样式问题
Oct 17 Javascript
@angular前端项目代码优化之构建Api Tree的方法
Dec 24 Javascript
基于Vue SEO的四种方案(小结)
Jul 01 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中日期加减法运算实现代码
2011/12/08 PHP
PHP中批量生成静态html(命令行下运行PHP)
2014/04/19 PHP
PHP中static关键字以及与self关键字的区别
2015/07/01 PHP
教你在PHPStorm中配置Xdebug
2015/07/27 PHP
PHP扩展mcrypt实现的AES加密功能示例
2019/01/29 PHP
Nigma vs Liquid BO3 第一场2.14
2021/03/10 DOTA
将input file的选择的文件清空的两种解决方案
2013/10/21 Javascript
JavaScript中提前声明变量或函数例子
2014/11/12 Javascript
js限制文本框的输入内容代码分享(3类)
2015/08/20 Javascript
JavaScript中this的9种应用场景及三种复合应用场景
2015/09/12 Javascript
javascript基础知识分享之类与函数化
2016/02/13 Javascript
深入理解JavaScript中的对象复制(Object Clone)
2016/05/18 Javascript
从零开始学习Node.js系列教程五:服务器监听方法示例
2017/04/13 Javascript
微信小程序中使用javascript 回调函数
2017/05/11 Javascript
微信小程序开发之实现自定义Toast弹框
2017/06/08 Javascript
JS原型继承四步曲及原型继承图一览
2017/11/28 Javascript
使用koa-log4管理nodeJs日志笔记的使用方法
2018/11/30 NodeJs
Mpvue中使用Vant Weapp组件库的方法步骤
2019/05/16 Javascript
关于layui的下拉搜索框异步加载数据的解决方法
2019/09/28 Javascript
Appium Python自动化测试之环境搭建的步骤
2019/01/23 Python
python Gunicorn服务器使用方法详解
2019/07/22 Python
python pandas cumsum求累计次数的用法
2019/07/29 Python
Python实现i人事自动打卡的示例代码
2020/01/09 Python
python tkinter GUI绘制,以及点击更新显示图片代码
2020/03/14 Python
Python中关于logging模块的学习笔记
2020/06/03 Python
python绘图pyecharts+pandas的使用详解
2020/12/13 Python
HTML5在手机端实现视频全屏展示方法
2020/11/23 HTML / CSS
H&M旗下高端女装品牌:& Other Stories
2018/05/07 全球购物
服务行业个人求职的自我评价
2013/12/12 职场文书
党员领导干部廉洁从政承诺书
2014/03/27 职场文书
终止合同协议书
2014/04/17 职场文书
火灾现场处置方案
2014/05/28 职场文书
公司人力资源管理制度
2015/08/05 职场文书
创业计划书之农家乐
2019/10/09 职场文书
详解nodejs内置模块
2021/05/06 NodeJs
Python办公自动化之教你如何用Python将任意文件转为PDF格式
2021/06/28 Python