在 javascript 中,原型链上的循环引用会导致 json.stringify() 抛出 typeerror: converting circular structure to json。要避免这个问题,最直接的做法是在序列化前使用 weakset 记录已访问的对象,并在遇到重复对象时返回特定标记(如 null)或跳过该属性。

如何安全地序列化包含循环引用的对象
通过遍历对象并维护一个 WeakSet,可以在递归过程中检测循环。当发现当前对象已在集合中时,直接返回 null 以避免无限递归和报错。

function serialize(obj, seen = new WeakSet()) {
if (obj === null || typeof obj !== 'object') return obj;
if (seen.has(obj)) return null;
seen.add(obj);
if (Array.isArray(obj)) {
return obj.map(item => serialize(item, seen));
}
const result = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
result[key] = serialize(obj[key], seen);
}
}
return result;
}
使用上述函数处理循环引用对象:
const a = { name: 'A' };
const b = { name: 'B', ref: a };
a.ref = b; // 形成循环
console.log(JSON.stringify(serialize(a)));
// 输出: {"name":"A","ref":{"name":"B","ref":null}}
为什么 WeakSet 是最佳选择
WeakSet 存储的是对象的弱引用,这意味着如果对象没有其他强引用指向它,垃圾回收器可以正常回收这些对象。这避免了内存泄漏问题,特别是在处理大型或动态创建的对象图时。

// 对比普通 Set 可能导致内存泄漏
const safeSerialize = (obj) => {
const seen = new WeakSet(); // 使用 WeakSet
function traverse(o) {
if (o && typeof o === 'object') {
if (seen.has(o)) return '[Circular]';
seen.add(o);
if (Array.isArray(o)) return o.map(traverse);
const res = {};
for (let k in o) res[k] = traverse(o[k]);
return res;
}
return o;
}
return traverse(obj);
};
const x = { val: 1 };
x.self = x;
console.log(safeSerialize(x));
基于程序中某个输入、条件或结果的具体问题
当输入对象包含非枚举属性或特殊类型(如 Date、RegExp)时,简单的递归序列化可能会丢失信息或转换错误。需要针对这些类型进行特殊处理,例如将 Date 转换为 ISO 字符串。
function robustSerialize(obj, seen = new WeakSet()) {
if (obj === null) return null;
if (typeof obj !== 'object') return obj;
if (seen.has(obj)) return '[Circular]';
seen.add(obj);
if (obj instanceof Date) return obj.toISOString();
if (obj instanceof RegExp) return obj.toString();
if (Array.isArray(obj)) return obj.map(item => robustSerialize(item, seen));
const result = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
result[key] = robustSerialize(obj[key], seen);
}
}
return result;
}
const data = {
created: new Date(),
pattern: /test/gi,
self: null
};
data.self = data;
console.log(JSON.stringify(robustSerialize(data)));
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











