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

小白:手写深拷贝的学习过程

时间:2023-03-27 23:13:36 HTML

今天逛segmentfault的时候看到很多大佬手写深拷贝。我记得也有大厂拿这个做题目,我也学学吧~之前都是直接用JSON.parse(JSON.stringfy())实现深拷贝。有时候在写业务的时候,有些错误可以使用深拷贝来解决。有一段时间,我居然认为“...[]”是数组的深拷贝...总之,这些知识还不够。开始编码!先了解一下浅拷贝和深拷贝的含义。之前的认知和现在的认知浅拷贝都是直接赋值,不仅是赋值,而且引用也是一样的——比如一个浅拷贝对象a到b,如果修改了a中的某个属性,则b中相应的属性也会发生变化。浅拷贝只能赋值最外层,比如objectobj1={a:{a:{a:1}}},浅拷贝到obj2,修改obj1.b=2,再修改obj1.b.b=2;输出ob2是{a:{a:{a:1}},b:2}。obj2.b不是对象。可以使用JSON.parse(JSON.stringfy())来实现,写业务基本够用了,还是依赖lodash的_.cloneDeep()实现。手写不会遇到转换失败的场景。JSON.parse(JSON.stringfy())有缺点:1.undefinedconversion会直接消失;2.RegExp转换会变成{};3.NaN,+-Infinity转换会变成null;4.环形引用会报错:TypeError:ConvertingcircularstructuretoJSON。我按照https://segmentfault.com/a/11...手动编写了代码。到最后都写的很好,也实现了功能。在这个过程中,我学到了很多知识——1、什么是基本类型和引用类型?基本类型:StringNumberBooleanUndefinedNull可回收引用类型:ArrayObjectMapSet不可回收引用类型:SymbolRegExpFunction2.如何判断类型?Object.prototype.toString.call(x)3.递归写法?functiondigui(sum){if(sum==0){返回0;}返回sum+digui(sum-1)}console.log(digui(6));4、如何复制Symbol?对象(Symbol.prototype.valueOf.call(x));5、for...in和for...of的区别for...infor...of推荐遍历对象——对象的键名,遍历数组——数组的索引(即,键名);枚举属性,包括原型推荐遍历数组-元素值;对象的遍历,不包括可枚举属性6.环引用是什么意思?如何解决它的深拷贝?环形引用意味着该值本身就是一个变量,可以使用Map来解析。具体解决办法见文章。此外,我还学习了如何复制函数、Symbol、RegExp、Map和Set。不过也有不明白的地方:思考第1行和第76行(见图1)是判断引用数据类型。通过输出可以看出,返回的temp是一个和origin同类型的null值,比如origin是{key:origin},那么temp就是{}。这个时候map已经保存了key为origin,value为{}的value——这不是错了吗?环引用变为{}(参见图3)。后来在origin只保留了一个changereference,然后debugger一步步往下走,发现递归走了两次,第一次执行map。键再次循环。因为第一个map.set,第79行代码(见图1)的if判断可以通过,从而设置了环引用的值。图1、图2、图3、图47、Map是如何取值和赋值的?varmap=newMap();map.get('key');map.set('key','value');8.什么是集合?Set是如何获取和赋值的?set类似于数组,但值是唯一的varset=newSet()set.add(1)set.delete(2)set.has(1)--->true/falseset.sizeset.clear()9.如何复制功能?思路:functiontoString,使用regular查找函数体和参数,返回newFunction(parameter,functionbody)10.如何复制RegExp?这个我不太明白,等我明白了再补充