要区分深拷贝和浅拷贝 先要了解js的两种数据类型
js 变量的类型包含两种,一种是基本类型,还有一种就是引用类型
基本类型包含 Undefined、Null、Boolean、Number和String
引用类型包含Object、Array、Date、Function等等
我们一般处理数据的时候使用Object和Array
我们在给变量赋值的时候就会因为数据类型不一样出现不一样的情况
基本类型的变量是按照值来访问的
例如
let a=1 let b=a a=2 console.log(a,b) //a=2,b=1
如上 a和b的值是互不干扰的
但是如果是引用类型的变量,就有点不一样了
例如
let a={ name:'李华' } let b=a a.name='张三' console.log(a.name,b.name) //张三
如上引用类型的变量的值是按照引用访问的,而不是实际的对象,(但是如果为对象添加属性,就是操作的是实际的对象)
如果仅仅是把一个对象赋值给一个变量,变量保存的仅仅是这个对象的引用,所以上面的a和b保存的是同一个对象的引用,只要改变了这个对象,保存这个对象的引用也随着变化了
浅拷贝和深拷贝都是创建了一个新的堆内存储存新的对象,而’=’操作只是保存了一个对象的引用
如果要实现浅拷贝
一、es6的…
let a={name:'zhangsan'} let b={...a} a.name='lisi' console.log(a,b) //{name: "lisi"} {name: "zhangsan"}
这样确实实现的深拷贝,重新给a.name 赋值不会影响到b的值
但是如果对象嵌套的比较深
let c={name:'zhangsan',son:{name:'zhangsi'}} let d={...c} c.son.name='老王' console.log(c,d,'name') //{name: "zhangsan", son: {name:'老王'} {name: "zhangsan", son: {name:'老王'}
此时 c和d 的son.name都变成’老王’了
es6的…就会存在这样的问题
但是不会丢失对象的方法
如果要实现深拷贝
二 先序列化,再反序列化
let c={name:'zhangsan',son:{name:'zhangsi'}} let d=JSON.parse(JSON.stringify(c)) c.son.name='老王' console.log(c,d,'name') //{name: "zhangsan", son: {name:'老王'}{name: "zhangsan", son: {name:"zhangsi"}
但是这个也会存在一些问题,会丢失对象的方法
let c={name:'zhangsan',son:{name:'zhangsi'},kill:function () { console.log('kill老王') }} let d=JSON.parse(JSON.stringify(c)) c.son.name='老王' console.log(c,d,'name')
如此操作之后c和d 都没有了kill方法