JS 中实现 Deep Clone (深克隆) 的思路
什么是深克隆,为什么要深克隆
深克隆就是将某个对象完全复制一份与原对象无任何关联的相同对象,重新分配新的内存。
为什么要使用深克隆呢,在 JS 中,对数据操作时,通常会如以下所示
- 基本数据类型的赋值
从上述代码不难看出,在对基本数据类型使用let a = 10; let b = 20; b = a; // 将 a 的值赋值给 b a = 30; console.log(a,b); // 30 10 // 对象中的基本数据类型的赋值 let data = { message:'clone' }; let data2 = { message:'clone2' }; data.message = data2.message; data2.message = 'clone3'; console.log(data); // {message:'clone2'} console.log(data2); // {message:'clone3'}
=
赋值的时候会重新分配内存空间使得两个变量在赋值之后隔离开不会相互影响 - 非基本数据类型情况下的属性引用赋值
从上诉代码我们可以看出,在let data = { meta: { message: 'clone'} }; let data2 = { }; data2.meta = data.meta; console.log(data2.meta.message); // clone data.meta.message = 'clone reassign'; console.log(data2.meta.message); // clone reassign
data2.meta = data.meta
这块代码中我们将 meta 这个非基本类型的属性赋值给了 data2 这个变量,然而,当我们改变 data 变量中 meta 的值时,data2 中的 meta 对象中的值也发生的改变。
由此我们可以知道在data2.meta = data.meta
中,实际上是将 data 对象中的 meta 对象的引用赋值给了 data2
从上诉两点我们可以得出结论 —— 在 JS 中,对变量赋值时,如果该变量是 基本数据类型 (比如: string, number, boolean, undefined 等)会重新分配内存空间,若该变量是一个对象,则会将该对象的引用赋值给目标变量。
所以,如果想要得到一个与原对象毫无关联的相同的新对象,简单地使用 =
是不能满足深克隆的需求的。
深克隆和浅克隆的区别
那什么是浅克隆呢,浅克隆可以理解为深克隆的简单化,下面我们通过代码来看看浅克隆和简单使用 =
的区别
// using '='
let a1 = a;
console.log(a1.number); // 1;
a.number++;
console.log(a1.number); // 2;
// other
let a2 = shallowClone(a); // shallowClone 是实现浅克隆的方法,暂不关心他是怎么实现的
console.log(a2.number); // 2;
console.log(a2.b.number); // 10;
a.number++;
a.b.number++;
console.log(a2