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

时间:2013-03-13 02:52:28

标签: javascript json equality deep-copy object-comparison

在尝试多次实现深度比较和复制JSON可序列化对象之后,我注意到最快的只是:

function deep_clone(a){
   return JSON.parse(JSON.stringify(a));
};
function is_equal(a,b){
    return JSON.stringify(a) === JSON.stringify(b);
};
但是,我觉得这是作弊。就像我会发现一些会在将来惹恼我的问题。使用它们没问题吗?

3 个答案:

答案 0 :(得分:13)

JavaScript不保证密钥的顺序。

如果按相同的顺序输入,这种方法大部分时间都可以使用,但不可靠。

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

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

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

答案 1 :(得分:9)

我意识到这是一个古老的问题,但我只是想在答案中添加更多内容,因为否则有人可能会错误地认为使用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}

这些怪癖可能会导致麻烦,即使订购不是一个问题(正如其他人所说,它可能是)。在大多数情况下,可能不太可能这些怪癖会让他们的头脑变得丑陋,但了解它们会很好,因为它们可能导致一些非常难以发现的错误。

答案 2 :(得分:1)

只要键值对总是以相同的顺序,是的,你可以使用stringify来比较使用深度等于运算符(===)。