第 95 题:模拟实现一个深拷贝,并考虑对象相互引用以及 Symbol 拷贝的情况
一个引用对象一般来说由两个部分组成:一个具名的 Handle,也就是我们所说的声明(如变量)和一个内部(不具名)的对象,也就是具名 Handle 的内部对象。它在 Manged Heap(托管堆)中分配,一般由新增引用对象的 New 方法是进行创建。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
分享一个来自 Vuex 的 deepCopy
解决了循环引用,cache 存储所有嵌套 obj 及其 copy 副本,以 cache 中是否有某个嵌套 obj 来判断是否循环引用,有则返回 引用的 copy
为什么没人用
getOwnPropertyDescriptors
@lhyt 的
在这种情况下有问题
感觉环状数据之前这个里面 #10 处理的方法可以
看大家都写的好复杂,我来一个简单点的吧。
@lhyt
函数为什么要拷贝?函数不是用来复用的吗?
Symbol 不是独一无二的吗?还能拷贝?
野路子
缺点:无法拷贝函数 、Symbol
var a=[];
a.push(a);
deepClone(a);
写个不用递归用循环的方式实现的版本吧
函数拷贝不了,还有一些奇奇怪怪的引用类型也拷贝不了,一般情况应该没啥问题,其实拷贝函数有一种思路是用AST(手动狗头)
new obj.constructor()
或eval(obj.toString())
创建一个新实例temp,并保存进map,通过Object.getOwnPropertyNames
和Object.getOwnPropertySymbols
遍历obj的所有属性名,递归调用deepClone完成temp上所有属性的声明和赋值,最后返回temp函数拷贝的情况太复杂了,所以就直接用了
eval(obj.toString())
数组的确是我忘了写return了。然后拷贝函数这种操作平时真不会有人做。如果实在是要拷贝,除了简单的function.toString和正则匹配外,还要考虑箭头函数、参数默认值、换行、this、函数名字
有两个问题:
target
是一个数组,拷贝结果没有返回target
是一个函数,函数没有被深拷贝一个不考虑其他数据类型的公共方法,基本满足大部分场景
主要问题是
我们另外用
getOwnPropertySymbols
可以获取symbol key可以解决问题1,用集合记忆曾经遍历过的对象可以解决问题2。当然,还有很多数据类型要独立去拷贝。比如拷贝一个RegExp,lodash是最全的数据类型拷贝了,有空可以研究一下另外,如果不考虑用symbol做key,还有两种黑科技深拷贝,可以解决环引用的问题,比stringify和parse优雅强一些
无论哪种方法,它们都有一个共性:失去了继承关系,所以剩下的需要我们手动补上去了,故有
Object.create(target.constructor.prototype)
的操作不知道有没有漏的。。