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去除空格的几种方法
Oct 03 Javascript
JavaScript使用prototype定义对象类型
Feb 07 Javascript
IE6 fixed的完美解决方案
Mar 31 Javascript
JS二维数组的定义说明
Mar 03 Javascript
jQuery随机密码生成的方法
Mar 09 Javascript
JQuery中上下文选择器实现方法
May 18 Javascript
jquery实现九宫格大转盘抽奖
Nov 13 Javascript
很棒的js选项卡切换效果
Jul 15 Javascript
react native带索引的城市列表组件的实例代码
Aug 08 Javascript
vue实现底部菜单功能
Jul 24 Javascript
vue实现form表单与table表格的数据关联功能示例
Jan 29 Javascript
AjaxFileUpload.js实现异步上传文件功能
Apr 19 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
PHP4实际应用经验篇(6)
2006/10/09 PHP
PHP生成指定随机字符串的简单实现方法
2015/04/01 PHP
typecho插件编写教程(六):调用接口
2015/05/28 PHP
WordPress的主题编写中获取头部模板和底部模板
2015/12/28 PHP
laravel框架关于搜索功能的实现
2018/03/15 PHP
php intval函数用法总结
2019/04/14 PHP
如何实现动态删除javascript函数
2007/05/27 Javascript
JavaScript中的公有、私有、特权和静态成员用法分析
2014/11/20 Javascript
javascript实现动态加载CSS
2015/01/26 Javascript
Javascript实现鼠标右键特色菜单
2015/08/04 Javascript
jQuery使用animate创建动画用法实例
2015/08/07 Javascript
jQuery实现选项联动轮播效果【附实例】
2016/04/19 Javascript
canvas的神奇用法
2017/02/03 Javascript
JS排序之冒泡排序详解
2017/04/08 Javascript
Angular.js 4.x中表单Template-Driven Forms详解
2017/04/25 Javascript
微信小程序获取微信运动步数的实例代码
2017/07/20 Javascript
dropload.js插件下拉刷新和上拉加载使用详解
2017/10/20 Javascript
详解javascript中的babel到底是什么
2018/06/21 Javascript
深入浅析Vue.js 中的 v-for 列表渲染指令
2018/11/19 Javascript
Three.JS实现三维场景
2018/12/30 Javascript
vue动态注册组件实例代码详解
2019/05/30 Javascript
机器学习python实战之手写数字识别
2017/11/01 Python
python中使用psutil查看内存占用的情况
2018/06/11 Python
Python 用turtle实现用正方形画圆的例子
2019/11/21 Python
python实现批量命名照片
2020/06/18 Python
pandas map(),apply(),applymap()区别解析
2021/02/24 Python
加拿大时尚少女服装品牌:Garage
2016/10/10 全球购物
美国校园市场:OCM
2017/06/08 全球购物
西班牙高科技产品购物网站:MejorDeseo
2019/09/08 全球购物
印度手工编织服装和家居用品商店:Fabindi
2019/10/07 全球购物
EJB timer的种类
2014/10/28 面试题
局领导领导班子四风对照检查材料
2014/09/27 职场文书
加强作风建设工作总结
2014/10/23 职场文书
会议通知
2015/04/15 职场文书
青年联谊会致辞
2015/07/31 职场文书
再读《皇帝的新衣》的读后感悟!
2019/08/07 职场文书