当前位置:首页>编程日记>正文

谈谈浅拷贝和深拷贝的区别,以及实现的方法

两者的区别:一个对象浅复制后,是深层次的对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会发生改变,而深复制的则是开辟了一个新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。

话不多说,上代码:

// 原始对象
var obj = { a:1, arr: [2,3],say:function(){console.log('hello')},obj1:{arr:[34,55,5],hand:function(){console.log('hand')},obj3:{a:1,take:function(){console.log('take')}}}
};// 开始浅复制
var shallowObj = shallowCopy(obj);// 定义浅复制逻辑
function shallowCopy(src) {var dst = {};for (var prop in src) {if (src.hasOwnProperty(prop)) {dst[prop] = src[prop];}}return dst;
}// 改变复制后的新对象属性值(第一层属性)
shallowObj.a = 2; 
shallowObj.arr = [9,8];
shallowObj.say = function(){console.log('world')
}// 打印新对象的及方法
console.dir(shallowObj)    
shallowObj.say();  // world// 打印原对象及方法
console.dir(obj);
obj.say();  // hello

结果如图所示:

谈谈浅拷贝和深拷贝的区别,以及实现的方法 配图01

结论 : 修改新对象的属性值,第一层的属性值的确没有变化,重点来了,我们给第二层以及更深层次的属性复制试试

// 原始对象
var obj = { a:1, arr: [2,3],say:function(){console.log('hello')},obj1:{arr:[34,55,5],hand:function(){console.log('hand')},obj3:{a:1,take:function(){console.log('take')}}}
};// 开始浅复制
var shallowObj = shallowCopy(obj);// 定义浅复制逻辑
function shallowCopy(src) {var dst = {};for (var prop in src) {if (src.hasOwnProperty(prop)) {dst[prop] = src[prop];}}return dst;
}// 改变复制后的新对象的属性值(第二层以及更深层次)
shallowObj.obj1.obj3.take = function(){console.log('shallowObj_take') 
}
shallowObj.obj1.hand = function(){console.log('shallowObj_hand')
}// 打印新对象的方法调用
shallowObj.obj1.obj3.take();  // shallowObj_take
shallowObj.obj1.hand();      // shallowObj_hand// 打印原对象的方法调用
obj.obj1.obj3.take();   // shallowObj_take
obj.obj1.hand();     // shallowObj_hand问题出现了:原对象的方法被新对象的修改,而产生变化。
原因是复制的是对象的地址指针,两个属性共同指向一个对象,只要其一发生变化,另一个也随之变化

深拷贝的方法:

1.可以递归递归去复制所有层级属性

// 原始对象
var obj = { a:1, arr: [2,3],say:function(){console.log('hello')},obj1:{arr:[34,55,5],hand:function(){console.log('hand')},obj3:{a:1,take:function(){console.log('take')}}}
};// 深复制逻辑(递归调用)
function deepClone(obj){let objClone = Array.isArray(obj)?[]:{};if(obj && typeof obj==="object"){for(key in obj){if(obj.hasOwnProperty(key)){//判断obj子元素是否为对象,如果是,递归复制if(obj[key] && typeof obj[key] ==="object"){objClone[key] = deepClone(obj[key]);}else{//如果不是,简单复制objClone[key] = obj[key];}}}}return objClone;
}    // 开始深复制
var shallowObj = deepClone(obj);// 改变复制后的新对象的属性值(第二层以及更深层次)
shallowObj.obj1.obj3.take = function(){console.log('shallowObj_take') 
}
shallowObj.obj1.hand = function(){console.log('shallowObj_hand')
}shallowObj.obj1.obj3.take();  // shallowObj_take
shallowObj.obj1.hand();      // shallowObj_handobj.obj1.obj3.take();   // take
obj.obj1.hand();     // hand结论:深拷贝后改变对象的属性值,不会影响原始对象的值。

2.除了递归,我们还可以借用JSON对象的parse和stringify

function deepClone(obj){let _obj = JSON.stringify(obj),objClone = JSON.parse(_obj);return objClone
}    
let a=[0,1,[2,3],4],b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);

3.除了上面两种方法之外,我们还可以借用JQ的extend方法

$.extend( [deep ], target, object1 [, objectN ] )

deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝

target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。

object1  objectN可选。 Object类型 第一个以及第N个被合并的对象。 


let a=[0,1,[2,3],4],b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);



http://www.coolblog.cn/news/50d5ae260a98cca2.html

相关文章:

  • asp多表查询并显示_SpringBoot系列(五):SpringBoot整合Mybatis实现多表关联查询
  • s7day2学习记录
  • 【求锤得锤的故事】Redis锁从面试连环炮聊到神仙打架。
  • 矿Spring入门Demo
  • 拼音怎么写_老师:不会写的字用圈代替,看到孩子试卷,网友:人才
  • Linux 实时流量监测(iptraf中文图解)
  • Win10 + Python + GPU版MXNet + VS2015 + RTools + R配置
  • 美颜
  • shell访问php文件夹,Shell获取某目录下所有文件夹的名称
  • 如何优雅的实现 Spring Boot 接口参数加密解密?
  • LeCun亲授的深度学习入门课:从飞行器的发明到卷积神经网络
  • Mac原生Terminal快速登录ssh
  • java受保护的数据与_Javascript类定义语法,私有成员、受保护成员、静态成员等介绍...
  • mysql commit 机制_1024MySQL事物提交机制
  • 支撑微博千亿调用的轻量级RPC框架:Motan
  • jquery 使用小技巧
  • 2019-9
  • 法拉利虚拟学院2010 服务器,法拉利虚拟学院2010
  • vscode pylint 错误_将实际未错误的py库添加到pylint白名单
  • 科学计算工具NumPy(3):ndarray的元素处理
  • 工程师在工作电脑存 64G 不雅文件,被公司开除后索赔 41 万,结果…
  • linux批量创建用户和密码
  • newinsets用法java_Java XYPlot.setInsets方法代碼示例
  • js常用阻止冒泡事件
  • 气泡图在开源监控工具中的应用效果
  • 各类型土地利用图例_划重点!国土空间总体规划——土地利用
  • php 启动服务器监听
  • dubbo简单示例
  • 【设计模式】 模式PK:策略模式VS状态模式
  • [iptables]Redhat 7.2下使用iptables实现NAT
  • Ubuntu13.10:[3]如何开启SSH SERVER服务
  • CSS小技巧——CSS滚动条美化
  • JS实现-页面数据无限加载
  • 阿里巴巴分布式服务框架 Dubbo
  • 最新DOS大全
  • Django View(视图系统)
  • 阿里大鱼.net core 发送短信
  • 程序员入错行怎么办?
  • 两张超级大表join优化
  • 第九天函数
  • Linux软件安装-----apache安装
  • HDU 5988 最小费用流
  • Sorenson Capital:值得投资的 5 种 AI 技术
  • 《看透springmvc源码分析与实践》读书笔记一
  • 正式开课!如何学习相机模型与标定?(单目+双目+鱼眼+深度相机)
  • Arm芯片的新革命在缓缓上演
  • nagios自写插件—check_file
  • python3 错误 Max retries exceeded with url 解决方法
  • 行为模式之Template Method模式
  • 通过Spark进行ALS离线和Stream实时推荐