先说一下答案:assign做的是浅克隆

“第一层是深克隆,下面的每一层做的是浅克隆” 这种说法其实是错误的。

   在我们去探究assign是深克隆还是浅克隆之前,我们必须先明白究竟什么是深克隆、什么是浅克隆?

问了一位大佬,是这么回答的

深浅克隆本质是看克隆后有没有指向同一个内存空间 - 牛客_上岸酱

这就是深、浅克隆的核心区别,网上有数不胜数的回答,但很少有这句话分析地如此简单而又透彻。

   回顾一下assign的用法

let obj2 = Object.assign({}, obj1);

assign发挥的作用,就是将obj1的属性克隆到一个空对象(取决于obj1的数据类型)中,然后让obj2指向这个对象。

我们一起看一个例子:

let obj1 = {m: 1,n: 2,attr: {name: 'Jack',age: 18}
}let obj2 = Object.assign({}, obj1);obj1.attr.name = 'Tom';
console.log( obj1.attr.name );  // Tom
console.log( obj2.attr.name );  // Tomobj2.attr.name = 'Jarry';
console.log( obj1.attr.name );  // Jarry
console.log( obj2.attr.name );  // Jarry

可以看到,obj1与obj2的attr依旧是耦合的状态,所以,很明显assign做的就是浅克隆

   还有很多人说,第一层是深克隆,更深的依旧是浅克隆

首先,这种说法一定是错误的。

按照这种说法,由obj1克隆出obj2,assign做的是深克隆。

但我们仔细观察上面的代码,obj2指向的对象,其实并非由assign创建,而是事先由我们创建。assign做的,只是将obj1的属性,克隆到这个事先被我们创建好的空对象中罢了。

注意事项:

  • assign在做属性拷贝过程,可能会产生异常,比如目标对象的某个只读属性和源对象的某个属性同名,这时该方法会抛出一个 TypeError 异常,拷贝过程中断,已经拷贝成功的属性不会受到影响,还未拷贝的属性将不会再被拷贝。
  • Object.assign() 拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。

它无法实现多层的深克隆

  我们来实现一个简单的多层深克隆

function deepCopy(o,c){var c = c || {}for(var i in o){if(typeof o[i] === 'object'){// 要考虑深复制问题了if(Object.prototype.toString.call(o[i]).slice(8, -1) === Array){// 这是数组c[i] =[];}else{//这是对象c[i] = {}}deepCopy(o[i],c[i])}else{c[i] = o[i]}}return c
}

这个方法只能作为一种思路,其在真正的应用中,还是会出现很多的问题。

  • 例如出现循环对象该如何处理?(a对象某个属性指向b对象,b对象中某个属性又是指向a对象)
  • 当对象的属性较多、深度够大时,使用递归,在性能上,也有很大的问题。

  ​​​​​​​ 目前,最好的解决方式,就是 lodash 中的 .cloneDeep(value) 方法,对ES6新增加的大多数数据类型都有考虑,性能上也是十分不错的。

JS 中的 assign 方法究竟是 “深克隆” 还是 “浅克隆”?相关推荐

  1. JS中通过call方法实现继承

    JS中通过call方法实现继承 原文:JS中通过call方法实现继承 讲解都写在注释里面了,有不对的地方请拍砖,谢谢! <html xmlns="http://www.w3.org/1 ...

  2. JS中的Replace方法

    最近查一个bug,原因是JS中的Replace方法造成的,当将一个字符串中有处需要替换时,一般会用到JS中的Replace方法,Replace方法的第一个参数如果是传的字符串,只会替换第一处.代码如下 ...

  3. java script eval_「eval」js中的eval方法详解(一)–eval方法的初级应用 - seo实验室...

    eval 在我看来,js中的eval()方法就是一个js语言的执行器,它能把其中的参数按照javaScript语法进行解析并执行. 语法: eval(s); eval()方法中的参数s有多种情况.参数 ...

  4. JS中创建对象的方法

    JS中创建对象的方法 最近手头一个项目刚完成,下一个显目还在准备中,趁这个空档期,拿起尘封多年的JS书, 重温一遍JS面向对象程序设计,然后就得出下文,算是一个总结吧. 也许,你会说 "创建 ...

  5. jquery中的map()方法与js中的map()方法

    1.jquery中的map()方法 首先看一个简单的实例: $("p").append( $("input").map(function(){ return $ ...

  6. js中的字符串方法与数组方法总结

    js中的字符串方法与数组方法总结 1.字符串方法 2.数组方法

  7. 请尽可能说出js中数组的方法,最少3个,越多越好

    我接下来要把数组方法全都过一遍,顺手做个整理. 至于为什么整理这个,最近总听说面试经常会问到这个问题, 面试官灵魂发问:请尽可能说出js中数组的方法,最少3个,越多越好 据可靠消息了解到,如果你回答的 ...

  8. slice在php里面什么意思,js中slice()使用方法

    本文主要和大家分享js中slice()使用方法,slice()通过索引位置获取新的数组,该方法不会修改原数组,只是返回一个新的子数组. 用法:arrayObj.slice(start,end)arra ...

  9. js中的slice方法(开始索引,结束索引-不包含该索引元素)-截取和splice方法-删除(开始索引,删除个数)和插入-(开始索引,删除个数,插入内容)

    js中的slice方法(开始索引,结束索引-不包含该索引元素)-截取和splice方法-删除(开始索引,删除个数)和插入-(开始索引,删除个数,插入内容) 1.slice(start,end)-截取 ...

最新文章

  1. html属性选择器怎么写,html – 具有“type”属性与make-up属性的CSS属性选择器和区分大小写...
  2. 20170914-构建之法:现代软件工程-阅读笔记
  3. 【数据结构】线性表大咖
  4. wampserver一系列问题总结
  5. 数据分析与挖掘建模实战003:单因子探索分析与可视化001数据案例介绍
  6. c语言课程设计--拼图游戏,C语言课程设计_拼图游戏.pdf
  7. ajax加载时间长,如何最好地处理需要很长时间才能完成的ajax请求?
  8. 「HNOI 2015」实验比较
  9. zeal刷新不出来_热血传奇:计算怪物刷新时间,升级速度立马不同,老玩家笑出了声。...
  10. UG 6.0软件安装教程
  11. 【重识云原生】第六章容器6.1.3节——Docker常用命令
  12. 最优化算法之鲍威尔算法(java)
  13. Trafodion建表之使用多温度特性
  14. 程序员转正答辩ppt
  15. PivotGridControl与ChartControl控件结合使用(一)
  16. 杂题 P1640 [SCOI2010]连续攻击游戏
  17. kafka报错:Replication factor:larger than available brokers
  18. 分治法解决赛程安排问题
  19. 如何考上复旦大学研究生
  20. 4000块一晚,住进地下88米深坑,这是全国首家AI超五星酒店

热门文章

  1. Word 2013去掉封面和目录的页眉
  2. python绘制gps路径_从GPS点绘制线
  3. android blackberry,BlackBerry 10将停止更新,但基于安卓的黑莓BB OS重获新生
  4. Android解析qq聊天记录表情
  5. 网易云信发布两大元宇宙解决方案,打响进军元宇宙第一枪
  6. 找工作之面试前准备概述
  7. 前端工程师必备的PS技能——切图篇
  8. 复杂工业系统故障诊断与安全控制方法
  9. VS2015_VisualStudio2015-Professional版
  10. 迎角、航迹角、侧滑角、圆周角、圆锥角