前端-深克隆与浅克隆
区别:浅克隆只是原始数据的引用,在堆中与原数据仍然共用一块内存。
深克隆为新数据在堆中重新分配一块内存。
浅克隆影响原始数据,深克隆不影响原始数据。
重点:javascript中有两种数据类型,分别是基础数据类型和引用数据类型。基础数据类型是按值访问的,常见的基础数据类型有Number、String、Boolean、Null、Undefined,这类变量克隆的时候会完整的复制一份;引用数据类型比如Array、Object,在克隆的时候克隆的是数据的引用,当克隆数据发生变化的时候,原数据也跟着变化。
常见的几种克隆方法:
1、直接赋值(浅克隆)
let aaa = {a:1,b:2,c:3};
let bbb = aaa;
bbb.a = '我被bbb改啦';
console.log(aaa); // {a: "我被bbb改啦", b: 2, c: 3}
2、Array.prototype.concat() 只针对最外层为数组(浅克隆)
let aaa = [{a:1,b:2,c:{a:3,b:4}}];
let bbb = aaa.concat(); // concat是连接数组,如果不传参,则表示复制原数组的数据到目标数组中
bbb[0].a = '我被bbb改啦';
console.log(aaa); // [{a:'我被bbb改啦',b:2,c:{a:3,b:4}}]
3、Array.prototype.slice() 只针对最外层为数组(浅克隆)
let aaa = [{a:1,b:2,c:{a:3,b:4}}];
let bbb = aaa.slice(); // slice是截取数组或者字符串,不传参表示默认全部
bbb[0].a = '我被bbb改啦';
console.log(aaa); // [{a:'我被bbb改啦',b:2,c:{a:3,b:4}}]
4、Object.assign()(可浅克隆也可深克隆)
// 一 原数据只有基础数据类型(深克隆)
let aaa = {a:1,b:2,c:3};
let bbb = Object.assign({},aaa);
bbb.a = '我被bbb改啦';
console.log(aaa); // {a: 1, b: 2, c: 3}
// 二 原数据有引用数据类型(浅克隆)
let aaa = {a:1,b:2,c:{a:3,b:4}};
let bbb = Object.assign({},aaa);
bbb.c.a = '我被bbb改啦';
console.log(aaa); // {a:1,b:2,c:{a:'我被bbb改啦',b:4}}
5、扩展运算符(...)(可浅克隆也可深克隆)
与Object.assign()克隆类似
//一 原数据只有基础数据类型 (深克隆)
let aaa = {a:1,b:2,c:3};
let bbb = {...aaa}; // 扩展运算符(…)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
bbb.a = '我被bbb改啦'
console.log(aaa);// {a:1,b:2,c:3}
// 二 原数据有引用数据类型(浅克隆)
let aaa = {a:1,b:2,c:{a:3,b:4}};
let bbb = {...aaa};
bbb.c.a = '我被bbb改啦';
console.log(aaa); // {a:1,b:2,c:{a:'我被bbb改啦',b:4}}
6、JSON.parse(JSON.stringify())(深克隆)
let aaa = [{a:1,b:2,c:{a:3,b:4}}];
let bbb = JSON.parse(JSON.stringify(aaa));
bbb[0].a = '我被bbb改啦';
console.log(aaa); // [{a:1,b:2,c:{a:3,b:4}}]