添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在使用 Ajax 请求时,有时需要传递一个复杂的对象给后端,此时需要使用 .stringify() 这个全局内置函数将对象序列化成 JSON 字符串,再传递给后端。如果这个要被序列化的对象被循环引用了,则序列化将会报错。

正文:

一、什么是循环引用


1
2
3
4
5
var obj = {
child: {}
}
obj.child = obj;
JSON.stringify(obj); // Uncaught TypeError: Converting circular structure to JSON

obj.two 引用了 obj 自身。这导致序列化时出现无限循环,所以执行 JSON.stringify() 方法时出现因为对象的循环引用而无法序列化对象的错误。

1
2
3
var arr = [];
arr[0] = arr;
JSON.stringify(arr); // Uncaught TypeError: Converting circular structure to JSON

数组也是引用类型,所以 arr 第一个元素 arr[0] 引用 arr 本身,出现无限循环的结构。导致序列化失败。

1
2
3
4
5
6
7
8
9
10
var obj_1 = {
childOne: {}
}
var obj_2 = {
childTwo: {}
}
obj_1.childOne = obj_2;
obj_2.childTwo = obj_1;
JSON.stringify(obj_1); // Uncaught TypeError: Converting circular structure to JSON
JSON.stringify(obj_2); // Uncaught TypeError: Converting circular structure to JSON

obj_1.two 引用了 obj_2 ,obj_2.two 引用了 obj_1 。执行 JSON.stringify(obj_1) 时, 会序列化 obj_1.two 引用的 obj_2 , 而 obj_2.two 又引用 obj_1 。这样导致循环引用。所以当两个对象相互引用对方,不管序列化哪个对象,这个对象都会因为循环引用序列化失败。

将两个独立的对象放到一个对象中进行循环引用是一样的,如下代码。

1
2
3
4
5
6
7
8
9
10
11
12
var obj = {
one: {
childOne: {}
},
two: {
childTwo: {}
}
}
obj.one.childOne = obj.two;
obj.two.childTwo = obj.one;
console.log(obj); // 可看到 obj 的结构中出现循环引用
JSON.stringfiy(obj); // Uncaught TypeError: Converting circular structure to JSON

那么循环引用就是一个对象自身的属性中出现引用这个对象本身的现象。导致对象某个结构的无限循环。取序列化这个无限循环的对象,当然就会出错。

二、序列化循环引用对象


如果这个对象就是存在循环引用的,想序列化这个对象,可以参考 JSON-js 库中的 cycle.js 。同时这个库也可将序列化的循环引用对象反序列化为原对象。

三、Ajax 传递给后台的参数循环引用如何解决


一般我们给后台的数据不应该出现循环引用问题。但是当对象、数组嵌套过多时,出现了循环引用的问题导致无法 JSON.stringify() 序列化。这时又很难找到循环引用的对象。一种解决方案就是使用 jQuery 中 $.extent() 方法将这个对象中的每个引用类型的对象都深拷贝一份新的对象,赋值给原对象属性。这也不失为一种解决方法。

The End