欢迎大家来到IT世界,在知识的湖畔探索吧!
写在前面:本文为DataHunter前端技术培训系列的第一篇文章,后续将有更多精彩内容放出,赶紧关注我们的公众号来get实时更新吧!
循环引用陷阱
JavaScript的GC机制是自动进行。当一个对象断开所有的指针引用以后,GC就会回收这部分资源。但循环引用会导致指针无法断开,请看如下代码:
由于a和b两个对象互相引用指针,形成了闭环,就会导致无法触发GC,所占资源也就无法释放。
在JSON.stringify对JavaScript数据结构进行序列化的时候,也会遇到循环引用的陷阱。例如:
JavaScript的数据类型和JSON序列化策略
通过JavaScript的typeof操作符,我们可以得到的数据类型有
string/number/ function/boolean/symbol/object/undefined。
其中object包括Object/Array/RegExp/Date/null等,function包括class类。所有这些类型,从JSON序列化的角度,我们可以分为三类:
由于JSON标准只具备string/number/boolean/null等有限的几种值类型,所以JS对象在序列化后会有变化。下面是几种特殊类型在转换时需要注意的问题:
-
function无法被序列化。
-
Symbol对象无法被序列化。
-
Date对象无法被序列化。
-
ES6的class的typeof是function,无法序列化。
-
number的NaN会被转成null。
-
RegExp默认会被转成空对象。
-
TypedArray并不继承自Array,所以会被序列化成对象而不是数组。
-
undefined由于会被JSON忽略,所以反序列化后对象会有键的变化。看例子:
可以看到,in操作符在obj和copy两个对象中会出现不同的返回结果。所以在对反序列化的数据进行操作时,in操作符要小心使用。
通过JSON的序列化策略我们可以看出,循环引用可能会发生在mixed类型上,所以我们可以在序列化过程的最外层,建立一个mixed指针的数组。当数组已经具备此指针,就可以断定该指针数据已经被序列化,从而中断进一步序列化过程。
首先我们写一个mixed类型判断函数:
通过JSON.stringify的第二个回调处理理函数参数,我们植入这个类型判断,并启用循环引用陷阱规避。
JavaScript对象的分支递归和深拷贝
我们知道,Object.assign会实现一次Object或者Array的浅拷贝。但这种浅拷贝有时并不能满足我们的需求。有时我们还会需要对对象的分支做值更改检测,或者分支合并。这时候都需要对对象的所有分支做一次递归。
JSON.stringify其实就是做了了一次分支递归。对象分支递归的策略和序列化策略基本一致,我们拿对象的深拷贝来举例说明。
我们首先针对上述三种数据类型,做一个类型判断函数。
此外,由于Object和Array都是mixed类型,但不是同一个构造函数,所以我们需要对Object和Array再做一次类型细分,以便构造新的复制对象。
创建一个分支递函数,并规避循环引用陷阱。
可以看到循环引用的部分都变成undefined了。
在ES6下,可以通过Symbol对象定义一个循环引用的标记并返回,在运行时对此类值做自定义的处理,防止对象log出来太难看。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/35456.html