如何辨别深拷贝与浅拷贝,简略点来说,就是假如B复制了A,当批改A时,看B是否会发生变化,如果B也跟着变了,阐明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};if(obj && typeof obj==="object"){ for(key in obj){ if(obj.hasOwnProperty(key)){ //判断ojb子元素是否为对象,如果是,递归复制 if(obj[key]&&typeof obj[key] ==="object"){ objClone[key] = deepClone(obj[key]); }else{ //如果不是,简略复制 objClone[key] = obj[key]; } } }}return objClone;
}
let a=[1,2,3,4],
b=deepClone(a);
a[0]=2;
console.log(a,b);
这里再次强调,深拷贝,是拷贝对象各个层级的属性,能够看个例子。JQ里有一个extend办法也能够拷贝对象,咱们来看看
let a=[1,2,3,4],
b=a.slice();
a[0]=2;
console.log(a,b);
那是不是说slice办法也是深拷贝了,毕竟b也没受a的影响,下面说了,深拷贝是会拷贝所有层级的属性,还是这个例子,咱们把a改改
let a=[0,1,[2,3],4],
b=a.slice();
a[0]=1;
a2=1;
console.log(a,b);
拷贝的不彻底啊,b对象的一级属性的确不受影响了,然而二级属性还是没能拷贝胜利,依然脱离不了a的管制,阐明slice基本不是真正的深拷贝。
这里援用知乎问答外面的一张图
第一层的属性的确深拷贝,领有了独立的内存,但更深的属性却依然专用了地址,所以才会造成下面的问题。
同理,concat办法与slice也存在这样的状况,他们都不是真正的深拷贝,这里须要留神。
除了递归,咱们还能够借用JSON对象的parse和stringify
function deepClone(obj){
let _obj = JSON.stringify(obj), objClone = JSON.parse(_obj);return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a2=1;
console.log(a,b);
能够看到,这下b是齐全不受a的影响了。
附带说下,JSON.stringify与JSON.parse除了实现深拷贝,还能联合localStorage实现对象数组存储。有趣味能够浏览博主这篇文章。
localStorage存储数组,对象,localStorage,sessionStorage存储数组对象