使用 JSON.stringify 进行深度比较和克隆是否合适?

新手上路,请多包涵

在尝试了几种用于 JSON 可序列化对象的深度比较和复制的实现之后,我注意到最快的通常是:

 function deep_clone(a){
   return JSON.parse(JSON.stringify(a));
};
function is_equal(a,b){
    return JSON.stringify(a) === JSON.stringify(b);
};

不过,我觉得这是在作弊。就像我会发现一些将来会惹恼我的问题一样。用那些好吗?

原文由 MaiaVictor 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 647
2 个回答

JavaScript 不保证键的顺序。

如果它们以相同的顺序输入,这种方法在大多数情况下会奏效,但并不可靠。

此外,对于深度相等但键输入顺序不同的对象,它会返回 false:

 JSON.stringify({ a: 1, b: 2}) === "{"a":1,"b":2}"

JSON.stringify({ b: 2, a: 1}) === "{"b":2,"a":1}"

原文由 dstreit 发布,翻译遵循 CC BY-SA 4.0 许可协议

我意识到这是一个老问题,但我只是想在答案中添加更多内容,因为否则有人可能会错误地认为使用 JSON.stringify 进行比较/克隆可以毫无问题地工作这么久因为它不用于比较/克隆其成员无序的对象。 (为了公平对待公认的答案,他们 不应该这样 想;它说,“如果[成员]以相同的顺序输入,这种方法在 大多数情况下都 有效。”)

代码可能最能说明潜在的问题:

 JSON.stringify(NaN) === JSON.stringify(null)
// => true

JSON.stringify(Infinity) === JSON.stringify(null)
// => true

// or, to put it all together:
JSON.stringify({ val1: (1 / 0), val2: parseInt("hi there"), val3: NaN }) === JSON.stringify({ val1: NaN, val2: null, val3: null })
// => true

// and here's the same example with "cloning" rather than comparison:
JSON.parse(JSON.stringify({ val1: (1 / 0), val2: parseInt("hi there"), val3: NaN }))
// => Object {val1: null, val2: null, val3: null}

即使订购不是问题(正如其他人所说,这可能是问题),这些怪癖也会造成麻烦。在大多数情况下,这些怪癖不太可能出现,但了解它们是件好事,因为它们可能会导致一些很难发现的错误。

原文由 Jason Rogers 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题