JavaScript - 循环引用错误
当一个对象创建对其自身的直接或间接引用时,这被称为循环引用。它会导致循环闭合。JavaScript 与其他编程语言一样,也存在循环引用问题。本章将讨论 JavaScript 循环引用模式中的一些错误。
什么是 JS 中的循环引用?
在 JavaScript 中,当两个或多个对象以某种方式相互引用并引发循环时,就会发生循环引用。例如,如果对象 A 引用对象 B,而对象 B 又引用对象 A,则会发生循环引用。
示例
以下是 JavaScript 中循环引用的基本示例 -
let person = {};
let friend = {};
// 创建循环引用
person.bestFriend = friend;
friend.bestFriend = person;
这会形成一个循环,其中 person 引用了一位朋友,而这位朋友又引用了此人。
循环引用问题
为了避免循环引用,最好在数据结构中避免对象间的交叉引用。
内存泄漏:当 JavaScript 的垃圾回收机制拒绝移除存在循环引用的对象,导致内存未被释放时,就会发生内存泄漏。
-
JSON 中的字符串化错误:当尝试将循环引用转换为 JSON 时,例如使用 JSON.stringify() 时,就会发生错误。由于此方法不支持循环结构,因此会产生错误。
let obj = {};
obj.self = obj;
// 抛出"TypeError: Converting looping Structure to JSON"错误
JSON.stringify(obj);
如何修复循环引用
可以使用一些标准方法来纠正循环引用。这些方法包括使用能够处理循环结构的特定库、在转换为 JSON 之前移除引用以及重新排列数据以防止循环。
移除循环引用
找到循环引用的位置,如果不需要,则将其移除。
let obj1 = {};
// 通过不将 obj1 指向 obj2 来避免循环引用
let obj2 = { obj1: obj1 };
console.log(JSON.stringify(obj2));
输出
这将生成以下结果 -
{"obj1":{}}
使用自定义 toJSON 方法
如果您想对具有循环引用的对象进行字符串化,您可以创建自定义 toJSON 函数来忽略它们。
let obj = {};
obj.self = obj;
obj.toJSON = function() {
let copy = { ...this };
// 消除循环引用
delete copy.self;
return copy;
};
// 现在运行起来不会出错
console.log(JSON.stringify(obj));
输出
输出结果如下 −
{}
使用库
一些库,例如 flatted 或 circular-json,可以自动处理循环引用。安装后,请使用该包代替 JSON.stringify()。
// 使用 circular-json
const CircularJSON = require('circular-json');
let obj = {};
obj.self = obj;
let jsonString = CircularJSON.stringify(obj);
// 将循环结构转换为 JSON 而不会出错
console.log(jsonString);
输出
这将产生以下结果 -
{"self":"~"}

