先说一下答案: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. R语言dplyr包对独特值(distinct)进行计数实战
  2. rabbitmq的整体架构一览
  3. 同一MODBUS读写多(两)个BH32角度传感器
  4. 利用nodeJs anywhere搭建本地服务器环境
  5. 1.10 访问对象的属性和行为
  6. 编译原理实验语义分析_「编译原理」LL(1)文法分析,简单优先分析
  7. 谷歌浏览器中打开IE
  8. BZOJ3157/BZOJ3516 国王奇遇记(矩阵快速幂/数学)
  9. Symantec清除工具 CleanWipe_14.3.558.1000
  10. Tomcat8zip版本安装与配置
  11. 图像预处理——对数变换
  12. 一个小时学会画网络拓扑图(附标准素材)
  13. 计算机word的关闭怎么办,为什么我的计算机word文档打开和关闭缓慢
  14. Service Mesh(服务网格)——后 Kubernetes 时代的微服务
  15. 2022年终总结:少年不惧岁月长,彼方尚有荣光在。
  16. 液晶面板价格高涨,OLED电视或迎来春天
  17. 脂多糖(LPS) 来源于肠炎沙门氏菌, S-型解决方案
  18. SMC 电气比例压力阀ITV型号索引及操作排故手册
  19. java后端开发面试题总结(一)
  20. X Chen笔记---Centos安装XWARE使用迅雷远程下载

热门文章

  1. 计算机学院运动会解说词,学院运动会解说词
  2. Hdu-5050 Divided Land(Java高精度)
  3. UI界面编写(仿QQ聊天界面)
  4. 右键点击文件显示多余菜单删除
  5. 下载的文件为什么会误报病毒?
  6. 从零开始学习使用iText PDF(1):生成第一个PDF文件
  7. 新概念 Lesson 5 How are you today
  8. 在鼠标点击特效上加上鼠标移动特效(一)
  9. 仿 IOS 桌面图标下载 view
  10. 电路习题解答 第一章 1-7、1-8