个人对赋值、浅拷贝和深拷贝的理解
术语
赋值
基本数据类型的赋值
对象数据类型的赋值
拷贝
浅拷贝
深拷贝
术语
基本数据类型:数字、字符串等这种。
对象数据类型:Object与Array这样的引用数据类型的。
赋值:可以看成等号连接,赋值的变量(等号左边)指向被赋值的变量(等号右边)
赋值
赋值看指向,觉得看字太累请直接理解代码。
基本数据类型的赋值
这里a的指向是一个1这个数字基本类型,
当b赋值2时等于是改变了b的指向,
b不指向a了,因此a不会改变
//这里a的指向是一个1这个数字基本类型 let a = 1; //这里b赋值a指向a let b = a; //b不指向a了,指向2这个数字基本类型 b = 2; console.log(a);//1 console.log(b);//2
对象数据类型的赋值
以下代码中,a赋值给b,对修改值与添加值,两个对象的内容完全一致
b和a指向同一个对象{},当b修改c添加d,但是没有对b直接进行赋值,因此
b还是指向a的,a内容也会同时改变
//a指向一个对象{ c: 1 } let a = { c: 1 } //b指向a let b = a console.log(a)//{ c: 1 } console.log(b)//{ c: 1 } //b修改指向的那个对象的内容 b.c = 2 b.d = 2 //由于b和a指向同一个对象{},因此b修改c添加d,a内容也会同时改变 console.log(a)//{ c: 2, d: 2 } console.log(b)//{ c: 2, d: 2 }
拷贝
浅拷贝与深拷贝都是对赋值的不同用法。
浅拷贝
下面这段觉得写的花里胡哨可以先不看以后理解了再来看加深印象,我们可以跳过直接看代码和图。
浅拷贝只复制指向某个对象的指针,不复制对象本身。只拷贝对象空间,而不复制资源。新旧指针同时共享一块内存。所以当拷贝来的对象修改的是非对象的基本数据类型,由于是改变了对象本身而不是改变了复制来的指针指向的对象的内容,所以原对象不会改变,如果修改的是对象数据类型,则会改变原对象里的内容。常见实现方式:Object.assign()
let a = { c: 1, z: { y: 1 } } let b = Object.assign({}, a) console.log(a)//{ c: 1, z: { y: 1 } } console.log(b)//{ c: 1, z: { y: 1 } }
浅拷贝就是对b新建了一个对象{c = a.c,z = a.z},对a里面的内容一一赋值到b
这里很关键,如果你对上文中提到的对象数据类型和基本数据类型的赋值有所理解就会知道
赋值c是基本数据类型的赋值,赋值z是对象数据类型的赋值
然后进行修改
let a = { c: 1, z: { y: 1 } } let b = Object.assign({}, a) console.log(a)//{ c: 1, z: { y: 1 } } console.log(b)//{ c: 1, z: { y: 1 } } //三个操作,基本数据类型的赋值,对象数据类型的赋值,基本数据类型的添加没有用到赋值 b.c = 2 b.z.y = 2 b.d = 2 //一一看赋值的属性 //b中的c是基本数据类型,原本指向a中的c,但是改变了指向指向了2 //b中的z是对象类型的赋值,修改的是和a中的z同一个对象,因此联动 //b中的d不是赋值来的,与a里面的内容无关 console.log(a)//{ c: 1, z: { y: 2 } } console.log(b)//{ c: 2, z: { y: 2 } , d : 2 }
以上代码用图如何理解呢?当b对a进行浅拷贝时,等于b新建了一个空间,对a的内容属性逐一进行指针拷贝,如果遇到基本数据类型等于是深拷贝,遇到对象数据类型等于是赋值,因为a和b不是一个空间,因此b添加d属性不会影响到a。
深拷贝
深拷贝是通过复制创造避开赋值带来的连锁反应,创造一个完全一样的对象,两个对象不会引起关联与变化。常见实现方式:JSON.parse(JSON.stringify())。
回过头看我们的对象数据类型的赋值,如果我们的b的是创建来的,那么与a无关不会引发联动
let a = { c: 1 } let b = { c: 1 } console.log(a)//{ c: 1 } console.log(b)//{ c: 1 } b.c = 2 b.d = 2 //a没改变 console.log(a)//{ c: 1 } console.log(b)//{ c: 2, d: 2 }
但是你会说这与深拷贝无关啊?拷贝过程呢?别急,如果你想拿a的数据来用啊,深拷贝是转变成字符串再转回对象,这个对象等于新建的,与a无关,这就是把a拿来深拷贝了。
let a = { c: 1 } //用深拷贝,等同于let b = { c: 1 } let b = JSON.parse(JSON.stringify(a)) console.log(a)//{ c: 1 } console.log(b)//{ c: 1 } b.c = 2 b.d = 2 //a没改变 console.log(a)//{ c: 1 } console.log(b)//{ c: 2, d: 2 }