转载声明:文章来源:https://blog.csdn.net/weixin_45452083/article/details/121852054
深浅拷贝是面试中经常会被问到的问题,这会帮大家整理一下,浅拷贝不写了,这次主要是深拷贝。
看段代码
let obj = {
a:1,
b:{
c: 1
},
}
let copyObj = obj
copyObj.a = 2
console.log(obj, copyObj)
这就浅拷贝了
1.JSON.parse(JSON.stringify(obj))
let copyObj = JSON.parse(JSON.stringify(obj))
copyObj.a = 2
console.log(obj, copyObj)
这样就成功了。
面试官:这种实现方案有什么问题吗?
答:该方法不能解决属性为函数,undefined,循环引用的的情况
上代码,看效果
let obj = {
a:undefined,
b:{
c: function() {
console.log(1)
},
d: null,
e: new Date(),
f: new RegExp('\\w+'),
g: NaN
},
}
let copyObj = JSON.parse(JSON.stringify(obj))
console.log(obj, copyObj)
1.原对象中的a、c不见了,undefined、function类型的key会丢失
2.e时间对象,会变成字符串形式
3.RegExp定义的属性会变成 {}
4.NaN 类型会变成 null
还有一个问题: 循环引用
let obj = {
a:1,
}
obj.c = obj
let copyObj = JSON.parse(JSON.stringify(obj))
console.log(obj, copyObj)
5.无法处理循环引用的问题
结论:这种拷贝方式局限性比较大,但是在日常开发中一般只是拷贝基本的数据类型,个人在开发中用的还是比较多
2.递归
一般我们会这样写
function copy(obj){
let newobj = null;
if(typeof(obj) == 'object' && obj !== null){
newobj = obj instanceof Array? [] : {};
for(var i in obj){
newobj[i] = copy(obj[i])
}
}else{
newobj = obj
}
return newobj;
}
面试官:递归实现有什么问题吗?
还是循环引用的问题
let obj = {
a:1,
}
obj.a = obj
let copyObj = copy(obj)
console.log(obj, copyObj)
还是会报错
解决:用 WeakMap() 或者Map()记录下对象中的所有对象,并与新创建的对象一一对应,即记录引用关系
let map = new Map(); // WeakMap
function copy(obj){
let newobj = null;
if(typeof(obj) == 'object' && obj !== null){
if (map.get(obj)) {
newobj = map.get(obj) // 如果不想循环打印 可以设置为null
} else {
newobj = obj instanceof Array? [] : {};
map.set(obj, newobj)
for(var i in obj){
newobj[i] = copy(obj[i])
}
}
}else{
newobj = obj
}
return newobj;
}
obj.b = obj
let copyObj = copy(obj)
console.log(obj, copyObj)
注意:如果遇到时间对象,正则等类型,需要通过new关键字去创建
3.jQuery.extend() 函数
jQuery.extend() 函数用于将一个或多个对象的内容合并到目标对象。
第一个参数是boolean类型,表示深浅拷贝,true表示深拷贝,false表示浅拷贝。只有两个参数,那么就把jQuery作为target,把第二个参数的字段赋给target,然后返回target。多于两个参数,把第二个参数作为target,然后把后面的参数的字段赋给target,最后面返回target.
let obj = {
a:1,
b: {
c:2
}
}
let copyObj = {}
$.extend(true,copyObj, obj);
copyObj.b = 3
console.log(obj, copyObj)
问题:当然如果两拷贝对象中有相同的属性名时,后者的值也会覆盖前者的值,就像这样:
let obj = {
a:1,
b: {
c:2
}
}
let obj2 = {
a:2,
d:4
}
$.extend(true,obj, obj2);
console.log(obj, obj2)
PS:jQuery这个框架现在使用量比较小,个人不做深入研究了
帖子还没人回复快来抢沙发