一、深浅拷贝的区别:
浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
简单理解:
假设B复制了A,修改A的时候,看B是否发生变化:
- 如果B跟着也变了,说明是浅拷贝(修改堆内存中的同一个值)
- 如果B没有改变,说明是深拷贝(修改堆内存中的不同的值)
二、实现深浅拷贝
1、浅拷贝:
<script>
let obj = {
a: 100,
b: [10, 20, 30],
c: {
x: 10
},
d: /^\d+&/
};
// 1.用for循环可以实现浅拷贝
let obj2 = {};
for (let key in obj) {
if (!obj.hasOwnProperty(key)) break;
obj2[key] = obj[key];
}
</script>
2、深拷贝:
<script>
let obj = {
a: 100,
b: [10, 20, 30],
c: {
x: 10
},
d: /^\d+&/
};
// 1.用ES6可以实现深拷贝
let obj2 = JSON.parse(JSON.Stringify(obj));
//这种方式会存在一定的弊端
// 1.对象中有正则时,会变成了空对象{}
// 2.对象中有函数时,也会变成了空对象
// 3.对象中有日期时,会把它变成字符类型
// 2.用递归实现深拷贝
function deepCopy(obj) {
if (obj === null) return null;
if (typeof obj !== "object") return obj;
if (obj instanceof RegExp) {
return new RegExp(obj);
}
if (obj instanceof Date) {
return new Date(obj);
}
// 不直接创建空对象 目的:克隆的结果和之前保持相同的所属类
let newObj = new obj.constructor;
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = deepClone(obj[key]);
}
}
return newObj;
}
// 3.比较好理解的递归写法
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
// 判断属性属于那种数据类型
var item = oldobj[k];
if (item instanceof Array) {
newobj[k] = [];
deepCope(newobj[k], item)
} else if (item instanceof Object) {
newobj[k] = {};
deepCope(newobj[k], item)
} else {
newobj[k] = item;
}
}
}
deepCopy(obj2,obj)
</script>