类型错误:循环对象值

当在 JSON 中找到对象引用时,会发生 JavaScript 异常 "循环对象值"。JSON.stringify() 没有尝试解决这些问题,因此失败了。

¥The JavaScript exception "cyclic object value" occurs when object references were found in JSON. JSON.stringify() doesn't try to solve them and fails accordingly.

信息

¥Message

TypeError: Converting circular structure to JSON (V8-based)
TypeError: cyclic object value (Firefox)
TypeError: JSON.stringify cannot serialize cyclic structures. (Safari)

错误类型

¥Error type

TypeError

什么地方出了错?

¥What went wrong?

JSON 格式 本身不支持对象引用(尽管有 IETF 草案已存在),因此 JSON.stringify() 不会尝试解决它们并相应地失败。

¥The JSON format per se doesn't support object references (although an IETF draft exists), hence JSON.stringify() doesn't try to solve them and fails accordingly.

示例

¥Examples

循环引用

¥Circular references

在如下所示的圆形结构中

¥In a circular structure like the following

js
const circularReference = { otherData: 123 };
circularReference.myself = circularReference;

JSON.stringify() 会失败

¥JSON.stringify() will fail

js
JSON.stringify(circularReference);
// TypeError: cyclic object value

要序列化循环引用,你可以使用支持它们的库(例如 cycle.js)或自己实现解决方案,这将需要通过可序列化的值查找和替换(或删除)循环引用。

¥To serialize circular references you can use a library that supports them (e.g. cycle.js) or implement a solution by yourself, which will require finding and replacing (or removing) the cyclic references by serializable values.

下面的代码片段说明了如何使用 JSON.stringify()replacer 参数查找和过滤(从而导致数据丢失)循环引用:

¥The snippet below illustrates how to find and filter (thus causing data loss) a cyclic reference by using the replacer parameter of JSON.stringify():

js
function getCircularReplacer() {
  const ancestors = [];
  return function (key, value) {
    if (typeof value !== "object" || value === null) {
      return value;
    }
    // `this` is the object that value is contained in,
    // i.e., its direct parent.
    while (ancestors.length > 0 && ancestors.at(-1) !== this) {
      ancestors.pop();
    }
    if (ancestors.includes(value)) {
      return "[Circular]";
    }
    ancestors.push(value);
    return value;
  };
}

JSON.stringify(circularReference, getCircularReplacer());
// {"otherData":123,"myself":"[Circular]"}

const o = {};
const notCircularReference = [o, o];
JSON.stringify(notCircularReference, getCircularReplacer());
// [{},{}]

也可以看看

¥See also