关于深拷贝和浅拷贝的概念---(引用关系)
深拷贝:
1、cpu在堆内存中重新开辟一个存储空间,用于储存这个完全克隆一个一模一样的对象;
2、在栈中会存储一个引用地址,用来指向新开辟的堆内存内容;
3、改变原对象,新对象不会改变;
浅拷贝:
1、不在堆内存中重新开辟空间,只复制拷贝对象栈内存中的引用地址。
2、改变原对象,新对象会改变;
3、本质上两个对象(数组)依然指向堆内存的同一块存储空间;
一、手动递归-遍历对象来拷贝
<!DOCTYPE html>
<html>
<head></head>
<body></body>
<script >
function deepCopy(obj) {
//typeof 数组,正则,日期,一般对象 都为object
if (typeof obj !== 'object' || obj === null) {
return obj;
}
// 1、处理日期对象
if (obj instanceof Date) {
// const copy = new Date();
// copy.setTime(obj.getTime());
// return copy;
return obj;
}
// 2、处理正则表达式对象
if (obj instanceof RegExp) {
// const flags = [];
// if (obj.global) flags.push('g');
// if (obj.ignoreCase) flags.push('i');
// if (obj.multiline) flags.push('m');
// return new RegExp(obj.source, flags.join(''));
return obj;
}
//3、区分对象和数组,初始化进行赋值
let copy = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
let aaa = {
a:/^[0-9]+$/,
b:{
c: new Date(),
d: [1,2,3]
}
}
deepCopy(aaa);
let bbb = deepCopy(aaa)
console.log('deepCopy',bbb,aaa)
// bbb
// {
// a:/^[0-9]+$/,
// b:{
// c: new Date(),
// d: [1,2,3]
// }
// }
// bbb
// {
// a:/^[0-9]+$/,
// b:{
// c: new Date(),
// d: [1,2,3]
// }
// }
</script>
</html>
二、JSON序列化和反序列化,JSON.stringify()和JSON.parse()
let obj = { a: 111, b: { c: 333 } };
let copyObj = JSON.parse(JSON.stringify(obj));
console.log(copyObj); // { a: 111, b: { c: 333 } }
该方法的坑:
1、丢失特定类型信息:正则,日期 作为属性值无法被拷贝,日期会变成字符串,正则在拷贝中直接转换为空对象;
2、无法拷贝函数和对象深度引用;
3、对象中属性值为undefined时会直接被忽略,做空值处理;
4、性能比较低;
三、使用第三方库(lodash)
const _ = require('lodash');
let obj = { a: 111, b: { c: 333 } };
let copyObj = _.cloneDeep(obj);
console.log(copyObj); // { a: 111, b: { c: 333 } }
四、jquery也有个深度拷贝方法
五、三点占位解析符,和Object.assign()方法不是用来拷贝的并且也不满足深度拷贝;
三点解构和Object.assign(),不是深度拷贝操作,它只是提取数据。浅拷贝和深拷贝是拷贝操作,前者只拷贝一层,下图中改变aaa属性中的c,bbb属性中的c也会被改变;
<!DOCTYPE html>
<html>
<head></head>
<body></body>
<script >
let aaa = {
a:/^[0-9]+$/,
b:{
c: new Date(),
d: [1,2,3]
}
}
let bbb = {
...aaa
}
console.log('deepCopy',bbb,aaa)
//bbb
// {
// a:/^[0-9]+$/,
// b:{
// c: new Date(),
// d: [1,2,3]
// }
// }
//aaa
// {
// a:/^[0-9]+$/,
// b:{
// c: new Date(),
// d: [1,2,3]
// }
// }
aaa.a = "xxx"
aaa.b.c = "999"
console.log('deepCopy',bbb,aaa)
//bbb
// {
// a:/^[0-9]+$/,
// b:{
// c: 999,
// d: [1,2,3]
// }
// }
//aaa
// {
// a:xxx,
// b:{
// c: 999,
// d: [1,2,3]
// }
// }
</script>
</html>