当前位置: 首页 > Web前端 > JavaScript

js的深拷贝和浅拷贝!

时间:2023-03-27 12:52:26 JavaScript

shallowcopy1,数组和对象的浅拷贝:letarr1=[1,2,3,4,5];letarr2=arr1;arr2[0]=5console.log(arr1);console.log(arr2);如上图所示,当我们改变arr2数组中的元素时,arr1页面也会随之改变,这让我们一时间无法理解到底是怎么回事。这时候,我们就可以利用之前所学的知识来理解!\我们学习了基本数据类型和参考数据类型。这里,arr1和arr2共享一个对象地址。对于这个对象地址,arr1只是将对象地址复制到arr2中,而不是在栈中创建新的存储空间!本章我们不会介绍太多关于栈的知识,后面会单独讲解!2.对象方法Object.assign():letobj2=Object.assign({},obj);obj2.age=20;obj2.child.name='feng';console.log(obj);console.log(对象2);从上图可以看出,当我们将obj.age改为20时,obj2发生了变化,而obj没有发生变化,我们认为已经实现了深拷贝。但是当我们在obj2对象中更改子对象中的名字时,发现obj和obj2都变了,也就是说内部子对象的引用地址还是一样的,这就证明这个方法也是浅显的copy,not将复制深层对象!同理,concat方法的结果也是一样的,都是浅拷贝!3、可以使用jes6的方法flat()实现浅拷贝:letarr=[1,2,[3,4,5,[6,7,8,9]]];letarr1=arr.flat();arr1[0]=0;arr1[2][0]=10;console.log(arr);console.log(arr1);这个es6方法flat()最初是为了实现数组的扁平化而引入的,但是这个方法也可以巧妙的实现数组或者对象的浅拷贝,如上图所示,和前面的Object.assign()方法是一样的,属于浅拷贝!深拷贝1.递归调用实现深拷贝:functiondeepClone(obj){letcloneObj=Array.isArray(obj)?[]:{};//你也可以这样做,这个在我们没有es6方法的时候常用isArray方法来判断一个对象是否是数组//letcloneObj=Object.prototype.toString.call(obj)==='[对象数组]'?[]:{};for(constkeyinobj){if(obj.hasOwnProperty(key)){//判断对象中的元素是否为对象if(obj[key]&&typeofobj[key]==='object'){cloneObj[key]=deepClone(obj[key]);}else{//如果不是对象,直接放入对象cloneObjcloneObj[key]=obj[键];}}}returncloneObj;}letobj=[1,2,{name:'peng'},5];obj1=deepClone(obj);obj1[0]=0;obj1[2].name='feng';console.log(obj);console.log(obj1);如上图所示,可以看到我们定义了一个方法deepClone深拷贝,通过递归遍历的方式将每个object中的一个object层的数据进行拷贝,保证复制的对象和之前的对象不是同一个对象,不会共享一个引用地址!当我们将数组的第一个元素和数组中对象的name属性更改为复制的对象时,不会影响到原来的对象,这样我们就实现了传统意义上的深拷贝!接下来看看有没有其他方法可以实现深拷贝!2.对象方法JSON.parse()和JSON.stringify()可以实现深拷贝:letobj={a:{b:'peng'}}letcloneObj=JSON.parse(JSON.stringify(obj));cloneObj.a.b='feng';console.log(obj)console.log(cloneObj);如上图,我们可以看到这个方法可以改变对象的深层数据,所以这个方法可以实现深拷贝!但是,这种方法有缺点;如果属性是undefined,则不会复制,如果属性不可复制,则不能像上面的undefined一样复制。如果属性是一个函数,那么就没有办法复制无法解决循环引用的对象,所以我们想办法。不要使用这种方法,但要知道!3、可以使用jQuery的方法extend()来实现深拷贝:$.extend([deep],target,object)第一个参数是是否是深拷贝,true是深拷贝,反之亦然;第二个参数是复制对象还是数组,第三个参数是要复制的目标值对象或数组letobj=[0,1,[2,3],4],obj1=$.extend(真,[],obj);obj[0]=1;obj[2][0]=1;console.log(obj);console.log(obj1);如上图所示,我们发现无论是一级数据还是二级数据,只有被修改的对象会发生变化,其他被复制的对象是不会发生变化的!实现深拷贝!小结其实深浅拷贝的目的就是复制的对象是否是一个全新的对象,如果是对一个对象的引用地址的普通引用,或者只能改变一层对象或数组的引用地址而不是整个数组或对象,如果层次都改变了,这就是浅拷贝。如果可以复制一个全新的对象,而且引用地址不同,那就是深拷贝!如果你长期使用深拷贝,请严格使用deeoClone方法!抄桥的话,那几个都差不多,大家可以自己考虑下,谢谢支持!