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

Mai*_*tor 13 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);
};
Run Code Online (Sandbox Code Playgroud)

不过,我觉得这是作弊.就像我会发现一些会在将来惹恼我的问题.使用它们可以吗?

dst*_*eit 14

JavaScript不保证密钥的顺序.

如果它们以相同的顺序输入,这种方法大多数时间都可以工作,但它不可靠.

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

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

JSON.stringify({ b: 2, a: 1}) === "{"b":2,"a":1}"
Run Code Online (Sandbox Code Playgroud)

  • 在最近的版本中,Javascript*确保*密钥订单.有关概述,请参见http://2ality.com/2015/10/property-traversal-order-es6.html.在实践中,JS引擎已经在这样做了.我认为,由于现在定义了键顺序,因此不应将具有不同顺序的相同键的两个对象视为等效.因此``JSON.stringify`比较有效. (4认同)

小智 11

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

即使在订购不是问题时,这些怪癖也会引起麻烦(正如其他人所说,它可能是这样).在大多数情况下,这些怪癖可能不会让他们的丑陋的头脑发挥作用,但是要注意它们是很好的,因为它们可能导致一些非常难以发现的错误.

  • 该问题询问“对JSON可序列化对象进行深度比较和复制”,因此,与包含函数的对象(窗口)相比,Infinity,NaN和不属于JSON的其他值实际上并没有更多相关性。对象,`undefined`,正则表达式等。 (2认同)