龙空技术网

【前端底层技术课堂】JavaScript对象的序列化和分支递归

DataHunter 333

前言:

眼前同学们对“js递归查找需要的值”大体比较关切,各位老铁们都需要剖析一些“js递归查找需要的值”的相关内容。那么小编也在网络上搜集了一些对于“js递归查找需要的值””的相关资讯,希望大家能喜欢,兄弟们一起来了解一下吧!

写在前面:本文为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出来太难看。

标签: #js递归查找需要的值 #js释放对象 #用递归反序输出字符串 #js对象序列化 #js将对象序列化