有这样一段代码,分别表示两个对象的关系,并尝试序列化其中一个:
var objA = {
name: 'this is A'
}
var objB = {
name: 'this is B'
}
objA.child = objB
objB.parent = objA
console.log(JSON.stringify(objA))你会惊讶的发现,得到一个错误:

当你打印出对象objA你会发现:

这个objA就跟愚公一样,头非常的铁,子子孙孙无穷尽也....这就是循环引用了。
怎么消除它呢?怎么中断这种一直循环的引用呢?
首先我们要知道一个东西,叫WeakMap
ECMAScript 6入门es6.ruanyifeng.com它的特性是,只能把object当着key来存值,其实就是寸的当前对象的内存地址。例如:
var peo = {
var: 'foo'
}
var man = peo
var wm = new WeakMap()
wm.set(peo, 'some value')
console.log(wm.has(man), wm.get(man))
所以,有了这个特性,我们可以对循环引用的对象做点判断:
某个属性如果引用了自己的父节点(上一级或者上上一级...),那么这个对象就存在循环引用。
代码如下:
function decycle (target) {
var map = new WeakMap()
function _cycle (obj) {
if (!map.has(obj)) {
map.set(obj, obj)
}
let keys = Object.keys(obj)
for (let i = 0, len = keys.length; i < len; i++) {
if (typeof obj[keys[i]] === 'object') {
if (map.has(obj[keys[i]])) {
obj[keys[i]] = '$'
continue
} else {
map.set(obj[keys[i]], obj[keys[i]])
}
_cycle(obj[keys[i]])
}
}
}
_cycle(target)
}验证一下是否可行:


结果是什么呢?

可以看到,把所有有循环引用的地方都终结了。
另外其实此段代码是有问题的,只作为基本原理的描述。
最后其实本文是受JSON-js的原理启发,如果遇到类似的问题,直接用这个就行:
JSON-jsgithub.com
452

被折叠的 条评论
为什么被折叠?



