我们都知道我们的数据类型分为两大类:
基本的数据类型有:number,string,boolean,null,undefined,symbol,引用数据类型(Object)有:{},[] 和函数当b=a进行拷贝时,其实复制的是a的引用地址,而并非堆里面的值。 而当我们a[0]=1时进行数组修改时,由于a与b指向的是同一个地址,所以自然b也受了影响,这就是所谓的浅拷贝了。 那,要是在堆内存中也开辟一个新的内存专门为b存放值,就像基本类型那样,岂不就达到深拷贝的效果了
浅克隆:直接将存储在栈中的值赋值给对应变量,如果是基本数据类型,则直接赋值对应的值,如果是引用类型,则赋值的是地址
基本数据类型是直接存储在栈内存中的,而引用数据类型,则仅仅是把地址存储在栈内存中,真正的数据是存储在堆内存中的,赋值操作时,仅仅把地址进行了赋值。
深克隆:就是把数据赋值给对应的变量,是拷贝对象各个层级的属性,在内存中开辟一块新内存,将原对象中的所有值全部复制过去,与原对象完全脱离,修改新对象中的属性值不会影响原对象、
obj2不会受obj的影响,因为被克隆的都是·基本数据类型,被存到栈中的东西,
如果obj中存在引用数据类型的话:
let obj ={ name:"xuke", age:22, hobby:{ first:"eat", second:"sleep" } } function clone(obj ){ const result = {} for(let key in obj){ result[key] = obj[key]; } return result } let obj2 = clone(obj) obj.hobby.first= "play" console.log(obj2.hobby.first) //play console.log(obj2==obj) //false我们可以看到obj2复制的obj中含有引用数据类型,我们修改了obj中的引用数据类型时,obj2中的也会改变,数据在复制的时候是把obj中的引用数据类型的地址一起复制过去了,所以obj和obj2使用的是一个地址,所以obj2会受影响,我们想要不受影响就要使用深克隆的方法。
JSON.parse(JSON.stringify())实现深度克隆的弊端:
1.对象中的方法不能进行copy,会自动忽略 2.对象中的Date时间不能进行copy, JSON.stringify方法会将日期自动转换为常规日期格式
3.正则表达式不能copy , JSON.stringify方法会将正则变为空对象
解决方法,用方法2将这些过滤掉: 2. 用递归实现深克隆
let obj ={ name:"xuke", age:22, hobby:{ first:"eat", second:"sleep" } } function clone(obj ){ // 过滤特俗情况 if(obj===null) return obj if(typeof obj !=='object') return obj if(obj instanceof RegExp){ return new RegExp(obj) } if(obj instanceof Date){ return new Date(obj) } let newObj = new obj.constructor for(let key in obj){ if (obj.hasOwnProperty(key)) { newObj[key] = clone(obj[key] ) } } return newObj } let obj2 = clone(obj) obj.hobby.first= "play" console.log(obj2.hobby.first) //eat console.log(obj2==obj) //false使用:当copy源中没有引用类型,方法,正则,日期等值,只是普通的数据类型时,我们就可以用浅拷贝的方法,反之用深拷贝