深浅拷贝

深浅拷贝

之前写Leecode24题的迭代算法时,一直以为是深拷贝,不断断点测试才知道,这是浅拷贝,这才知道底层设计时,拷贝都是浅拷贝。果然算法前还是得把语言特性理解了。

深拷贝的实现方式(超全) - 掘金 (juejin.cn)

让我们先定义一个对象

1
2
3
4
5
6
7
const oldObj = {
name:'zono',
colors:['orange','green','blue'],
friend:{
name:'童馨'
}
}

浅拷贝

让我们进行一次拷贝

1
2
3
4
const newObj = oldObj;
newObj.name = 'xiao';
console.log('oldObj',oldObj);
console.log('newObj',newObj);//输出相同都是xiao

可见浅拷贝,会让原本被拷贝的源对象的属性也一起改了。

可见浅拷贝就只是换一下指向的对象,只简简单单地把栈当中的引用地址拷贝了一份

排除上文的算法题用到浅拷贝,有时我们可能想用到深拷贝

深拷贝

概念:深拷贝就是创建一个新对象,对象改变不影响原来的对象

方法:调用库或者使用第三方库

法一 递归

为了不只最外层被拷贝

一般

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function deepClone(obj){
const newObj = {};
let keys = Object.keys(obj);
let key = null;
let data = null;
for(let i = 0; i<keys.length;i++){
key = keys[i];
data = obj[key];
if(data && typeof data === 'object'){
newObj[key] = cloneDeepDi(data)
}else{
newObj[key] = data;
}
}
return newObj
}

循环引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function deepCopy(obj, parent = null) {
// 创建一个新对象
let result = {};
let keys = Object.keys(obj),
key = null,
temp = null,
_parent = parent;
// 该字段有父级则需要追溯该字段的父级
while (_parent) {
// 如果该字段引用了它的父级则为循环引用
if (_parent.originalParent === obj) {
// 循环引用直接返回同级的新对象
return _parent.currentParent;
}
_parent = _parent.parent;
}
for (let i = 0; i < keys.length; i++) {
key = keys[i];
temp = obj[key];
// 如果字段的值也是一个对象
if (temp && typeof temp === 'object') {
// 递归执行深拷贝 将同级的待拷贝对象与新对象传递给 parent 方便追溯循环引用
result[key] = DeepCopy(temp, {
originalParent: obj,
currentParent: result,
parent: parent
});

} else {
result[key] = temp;
}
}
return result;
}

法二Object.assign

也只对最外层拷贝

1
2
3
4
function cloneDeepAssign(obj){
return Object.assign({},obj)
//Object.assign({},obj)
}

(温馨提示:数组拷贝方法当中,使用...sliceconcat等进行拷贝也是一样的效果,只深拷贝最外层)

法三json

复盘联系

深浅拷贝和原型链的关系