我有一个要序列化为String的JavaScript对象:

key                     {...}       Object
    mandant             "00001"     String
    personalNummer      600235      Number


首先,我使用JSON2,其返回值为undefined。使用JSON3,我得到一个TypeError,并且json3.js行中的注释说:

// Cyclic structures cannot be serialized by `JSON.stringify`.


该问题似乎是由json3.js中的以下行引起的:

// Manually invoke the callback for the `constructor` property due to
// cross-environment inconsistencies.
if (isConstructor || isProperty.call(object, (property = "constructor"))) {
    callback(property);
}


但是应该没有周期,我很显然无法弄清楚到底发生了什么。

当我在调试时手动创建对象时,一切正常。

那么,什么会引起错误呢?



编辑:
我成功地准备了一个场景来产生错误:


只是在具有兼容模式IE7和IE8的IE9中发生(Firefox 22也可以)
如果打开了一个新窗口并引用了打开窗口中的数据,就会发生这种情况



* JSON_Cycle.html *:

    <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="http://bestiejs.github.io/json3/lib/json3.js"></script>
    <script>
    var dataGlobal = {mandant: "Hallo Welt!", personalNummer: 123456};
        $(function() {
            window.open("JSON_Cycle_Popup.html", 'popup');
        });
    </script>



* JSON_Cycle_Popup.html *:

<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="http://bestiejs.github.io/json3/lib/json3.js"></script>
<script>
    var dataGlobal = null;
    $(function() {
        dataGlobal = window.opener.dataGlobal;
        alert(JSON.stringify(dataGlobal));
    });
</script>

最佳答案

现在,根据您问题中的新信息,我可以解释发生了什么。

在您的JSON_Cycle.html文件中,在dataGlobal变量初始化后添加以下行。

alert(typeof dataGlobal.constructor);


现在,在JSON_Cycle_Popup.html中执行相同的操作。注意区别吗?在IE上,第一个警报显示构造函数的类型为“函数”,但在弹出窗口中,相同的构造函数返回“对象”类型。

这是第一个问题。下一个问题来自json3枚举对象属性的方式。它们不仅使用常规的for循环,即for (property in object) ...。他们有很多代码试图检测不同浏览器实现之间的不一致,以产生一个在所有平台上返回相同结果的枚举器。

该枚举器的作用之一是,即使通常不会在for循环中返回一个对象,它也会为每个对象返回一个构造函数属性。这似乎完全没有必要,因为您显然仍然不想在json对象中序列化构造函数。但是我怀疑这段代码是从其他一些需要这种行为的项目中继承的。

这两个问题的结合,意味着在序列化dataGlobal对象时,json3将找到它将尝试处理的构造函数属性。然后,当序列化该构造函数(它认为是另一个对象)时,它将找到另一个构造函数属性(同样看起来是一个对象)。如果不是下一个问题,这个过程将继续到无限。

在四个层次的构造函数嵌套之后,函数指针循环。即:

dataGlobal.constructor.constructor.constructor.constructor ==
dataGlobal.constructor.constructor


我不知道为什么会这样,但是在我测试过的所有浏览器中似乎都是这样。这意味着json3代码没有检测到无限递归,而是检测到一个循环并抛出TypeError异常。

这就是您的错误的解释。 IE中的错误加上json3属性枚举器方面的不必要的聪明。

09-25 19:25