深浅拷贝
这篇总结深度讲解了深浅拷贝,希望能帮到你
这篇文章,我说说深浅拷贝,虽然很多人说它只针对引用类型,但是
1.深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的,同时,
2.它只有当拷贝引用数据类型时,拷贝才存在浅拷贝与深拷贝之分。
他们两个都会开辟一个新的内存空间,浅拷贝中的数据是值类型时,他会拷贝他的值,拷贝的数据是引用类型时,则是他的地址,例如:
let obj = {
a:1,
b:2,
c:{
d:4,
f:5
}
}
let obj2 = Object.assgin({},obj)
/*此时里面的a,b都是值类型,当你这个obj这个对象被obj2浅拷贝过去,
当obj2修改a,b时,是影响不到obj中的a,b的,如果是修改c的数据,
那么就会影响到obj中c的数据,因为c拷贝的是地址。同时,有些人在想,
当他利用obj2.c = {d:5,f:888},他说这么写,obj2的数据明明改变了,
obj1为啥不变?拜托大哥,麻烦你把堆和栈搞明白了再学后面的,
这样修改是修改的是整个对象,也就是说,地址都变了,还怎么相互影响?*/
深拷贝呢?
它同样会开辟一个新的空间,只不过他拷贝引用类型的时候拷贝的不再是他的地址,而是他的数据!因此,无论你如何修改他都不会影响原来的数据
如何进行浅拷贝?
拷贝对象
方法1:Object.assign(拷贝对象给谁,被拷贝的对象)
方法2:展开运算符 {...被拷贝的对象}
拷贝数组
方法1:Array.prototype.concat()
方法2:展开运算符[...arr]
此时大多数人都有一个困惑点,在想直接赋值是不是浅拷贝,我可以狠狠的自信的告诉你,不是!不要再认为直接赋值是浅拷贝了,直接赋值拿到的是地址,修改会影响原来的数据
如何进行深拷贝 ?
常见方法方法1:通过递归实现深拷贝方法2:lodash/cloneDeep
let 新对象 = _.cloneDeep(老对象)
方法3:通过JSON.parse(JSON.stringify(js对象))实现
let 新对象 = JSON.parse(JSON.stringify(js对象))
在此,我强调一下,利用JSON实现的深拷贝,并非真正意义上的深拷贝。为什么呢?有以下几点原因!
1.如果obj里面存在时间对象,JSON.parse(JSON.stringify(obj))之后,时间对象变成了字符串。
2.如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象。
3.如果obj里有函数,undefined,则序列化的结果会把函数, undefined丢失。
4.如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null。
5.JSON.stringify()只能序列化对象的可枚举的自有属性。
6.如果obj中的对象是有构造函数生成的,则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor。
7.如果对象中存在循环引用的情况也无法正确实现深拷贝。