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

JavaScript中的深拷贝和浅拷贝

时间:2023-03-26 21:08:04 JavaScript

JavaScript内存堆和栈(stack):堆是JavaScript用来存储静态数据的一种数据结构。静态数据是引擎在编译时知道其大小的数据。从ES2021开始,在JavaScript中,这包括7个原始值(string、number、boolean、bull、undefined、bigInt、symbol)以及对对象和函数的引用。堆:堆是存储数据的不同空间,JavaScript存储对象和函数。定义是将一个变量的值赋值给另一个变量,相当于在栈内存中新建一块内存空间,然后从栈中复制值存入这块新空间。1.对于基本类型来说,栈中存放的是自己的值,所以新的内存空间也存放了一个值。直接改变新变量的值不会影响旧变量的值,因为它们存放值的内存空间不同。因此,将基本变量a的值复制到另一个变量b时,改变b的值不会影响原变量a本身的值。2、对于引用变量,栈主要存放的是它引用的对象的地址。因此,当将引用变量a的值复制到另一个变量b时,a和b实际上都指向了堆中同一个内存地址。所以改变b的值就相当于改变了b指向的堆中的值,所以a也会随之改变。所以我们一般说的是引用类型的深拷贝和浅拷贝。因为对于值类型来说,它的拷贝结果都是深拷贝。浅拷贝:将旧引用变量的值赋给新引用变量时,将旧引用变量中存储的地址复制到新引用变量中。这意味着新旧引用变量都指向内存中的同一个对象。因此,如果对象的状态通过引用变量中的任何一个发生变化,它都会反映两者。深拷贝:深拷贝复制旧对象的所有成员,为新对象分配单独的内存位置,并将复制的成员分配给新对象。这样,两个对象就相互独立了,对一个对象的任何修改都不会影响另一个对象。简而言之,如果一个对象a被复制到另一个对象b,如果b被修改,a也会改变,这就是浅拷贝。反之,如果a保持原来的值,就是深拷贝。浅拷贝实现首先声明一个引用类型对象person,如下:letperson={name:"Emon",job:"developer"};1.直接赋值letshallowCopyPerson=person;2.Object.assign(target)`Object.assign(target,source1,source2...)`最初将一个或多个源对象的所有可枚举属性的值赋值给目标对象。返回目标对象。常见用法:consttargetObj={a:1,b:2};constsourceObj={c:3,d:4};Object.assign(targetObj,sourceObj);//{a:1,b:2,c:3,d:4}console.log(targetObj);//{a:1,b:2,c:3,d:4}这里我们可以用来复制对象:letshallowCopyPerson=Object.assign(person);1.遍历赋值,这种方法虽然遍历了对象,但本质是复制对象的引用。这些副本的结果都是指针的副本,所以改变shallowCopyPerson的属性后,原对象person的属性也会改变,结果如下:shallowCopyPerson.name="lucy";//改变复制的值console.log(shallowCopyPerson);//{name:'lucy',job:'developer'}复制的对象已经改变。控制台日志(人);//{name:'lucy',job:'developer'}请注意,目标对象本身也会发生变化。深拷贝实现深拷贝的实现方式其实有很多种。这里简单介绍几个比较方便快捷的。Object.assign({},来源);这种方法与上面的浅拷贝实现略有不同。它将目标设置为一个空对象,然后将源对象传入,实现复制JSON.parse/stringify有很多限制,如果你需要复制的对象没有函数,undefined,Infinit或者更复杂的类型像RegExps,Maps,Sets,Blobs,FileLists,ImageDatas等等。那么你可以使用这个方法。consta={string:"string",number:123,bool:false,nul:null,date:newDate(),//stringifiedundef:undefined,//lostinf:Infinity,//强制为'null're:/.*/,//lost,to{}fun:()=>"helloworld",//lost};遍历赋值我们可以通过遍历原来的object对象,将里面的值一个一个重新赋值给新的。letshallowCopyPerson={};for(constkeyinperson){shallowCopyPerson[key]=person[key];}structuredClone()method这是JS官方定义的方法。遗憾的是,目前主流的浏览器都不支持这种方式。最新的浏览器支持结果可以参考structuredClone。constshallowCopyPerson=structuredClone(person);