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

js深浅拷贝(简单解释原理)

时间:2023-03-27 15:47:54 JavaScript

需要了解栈的基本知识堆栈,系统自动分配的内存空间,堆堆由系统自动释放,动态分配的内存,堆数据是随机存储的指向栈内存的指针js数据类型基本数据:变量和值都是指栈中的数据,即变量存在于栈中,但值是对象。这是堆内存中存储的基本数据类型:undefined、null、boolean、number、string,这几种类型通过值访问,可以操作变量中存储的实际值引用数据类型:object、array、function、dateobject等等,很可能一个对象可以由多个值组成。js不允许直接访问内存位置,所以当我们操作对象时,我们只是在操作对对象的引用,而不是实际的对象。深浅复制原理理解深浅复制理解,复制就是复制,引用类型数据的js数据复制,浅复制。由于引用类型数据存放在堆内存中,引用类型的值存放在堆内存中,引用数据可能是指向栈内存的指针,而浅拷贝的指向栈内存的指针是一致的,所以改变一个也会影响另一个。深拷贝就是在堆内存中开辟一块新的空间来存放数据。简单的理解就是:如果拷贝产生新的数据,就是深拷贝,如果只是对数据的引用,就是浅拷贝vara=[1,2,3]varb=a//This是地址,传递给变量的数据是引用数据时,数据会存放在堆中。所以,引用数据就是变量名在栈上,值在堆上varc=a[1]//这是传一个值,直接给变量赋值,这个c就是基础数据类型,存储在栈中,改变栈上的数据不会影响堆上的数据此时:改变b的值,b[1]=3,此时a[1]也会变成3但是你改成c=7,a[1]还是之前的值,不会变成7。理解:a是引用数据,b=a是把栈中的地址传给b,而是存放数据的对象堆内存中还是一样,相当于只增加了一个栈内存指针指向同一个堆内存。所以修改b会根据内存修改到a的堆中,所以b变化=>a变化。而c是在堆内存中获取一个值,保存在栈中。c的修改是栈修改,不能保存到堆中,所以a不会受到影响。注:基础数据只是栈中的一份拷贝,与深浅拷贝无关(深浅拷贝只与引用数据有关)**题外话:js的垃圾回收机制是处理内存的。栈基本用完就回收了。检查堆上是否有变量全部调用后才回收。我也是一知半解。详情视具体资料而定。可以参考阮一峰老师的详细讲解:http://www.ruanyifeng.com/blo...代码实践(实现深浅拷贝)vara={age:'123',hobby:['basketball','singing','watchmovie']}varaCopy={}目的:实现浅拷贝a和深拷贝a到aCopy,使用递归###我们用a形参替换复制的对象,b形参替换目标拷贝对象###浅拷贝###由于我们不是遍历数组,而是遍历对象,所以我们使用forinfunctionshallowCopy(a,b){for(varattrina){b[attr]=a[attr]}}shallowCopy(a,aCopy);//实现浅拷贝//此时只需要删除修改a的基础数据age和引用数据favorite即可看到aCopy的基础数据不会变,但是引用的数据会变###深拷贝(递归:简单的说自己调用,用栈压栈出栈,先入后出)这个栈流程图使用的方法在图b下面解释函数a(){b();console.log('a');返回}functionb(){console.log('b');返回}函数c(){a();b();console.log('c')}c()流程图的block表示栈图LR入栈流程中第一次D[empty]-->AA[c]-->B[a,c]B-->C[b,a,c]弹出过程中第一次A1[b,a,c]-->B1[a,c]B1-->C1[c]pushA2[c]第二次-->B2[b,c]第二次popA3[b,c]-->B3[c]第三次A4[c]-->B4[empty]理解原理需要理解并开始编写代码functiondeepCopy(a,b){for(varattrina){varitem=a[attr];//取出待复制对象的属性数据,判断是否为复制的参考数据if(iteminstanceofArray){b[attr]=[];//这个空数组是我们暂存数据的地方,开辟新的存储数据,实现深拷贝deepCopy(item,b[attr]);}elseif(iteminstanceofObject){b[attr]={};deepCopy(item,b[attr])}else{b[attr]=item;}}}deepCopy(a,aCopy);修改a的引用数据收藏夹,可以发现a,aCopy不会改变浅拷贝object.assign,因为只拷贝了对象的值,属于浅拷贝三点算子等价的Object.assign(),复制数组最好换成这个,原因看了上面的内容就知道了。普通assignmentcopydeepcopyJSON.parse(JSON.stringify(arr/obj)):arrayorobjectdeepcopy,但不能处理函数数据递归遍历