405 字
2 分钟
@graphif/serializer 引用机制的原理
WARNING

算法有待优化,不建议学习

概念#

在一个对象中,经常会有「两个键指向相同的对象」的情况,这种情况下,可以将第二个键的值设为一个特殊的对象以节省空间,即「引用」。

前言#

@graphif/serializer 以前的版本中,没有考虑到相同的对象可以被优化。

现在,既然我想到了,就把它做出来。

哪些对象可以被优化?#

并不能粗暴地将所有相同的对象都优化,只有那些「比较复杂」的对象才有可能被优化。

比如,我这里通过「字符串值总长度」和「键值对数量」两个指标来判断一个对象是否比较复杂。

function isComplex(obj: Record<string, any>): boolean {
const stringLengthTotal = Object.values(obj)
.filter((v) => typeof v === "string")
.reduce((acc, v) => acc + v.length, 0);
return Object.keys(obj).length > 5 || stringLengthTotal >= 50;
}

「引用」如何表示?#

@graphif/serializer 中,用 $ 作为引用的标志。

[{ "hello": "world" }, { "$": "/0" }]

在上面的例子中,第二个对象引用了第一个对象。

$ 的值是一个路径,类似 XPath,但是全部使用 / 分隔,数组也是。

怎么知道对象对应的路径?#

首先生成一个「对象 ID」,可以用任意算法生成,只要保证唯一性即可。

例如,我使用 md5 哈希算法和 MsgPack 编码生成。

const okey = md5(encode(result));
NOTE

okey == Object Key

然后,将「对象 ID」和「路径」对应起来即可。

const obj2path = new Map<string, string>();

#

第一次做这种东西,尝试了几个小时才成功,效果还行。

不管了,以后有时间再重新搞一遍吧。

@graphif/serializer 引用机制的原理
https://2y.nz/p/serializer-ref/
作者
zty012
发布于
2025-08-06
许可协议
CC BY-NC-SA 4.0