使用JSON可以吗?严格的比较和克隆?

时间:2021-05-24 06:50:07

After attempting several implementations for deep comparison and copying for JSON-serializable objects, I've noticed the fastest often are just:

在尝试了几个实现对JSON-serializable对象进行深度比较和复制之后,我发现最快的实现通常是:

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

I feel like this is cheating, though. Like I'll find some problem that will annoy me on future. Is it fine to use those?

我觉得这是作弊。就像我会发现一些问题,将来会让我烦恼。可以用那些吗?

3 个解决方案

#1


10  

JavaScript does not guarantee the order of keys.

JavaScript不保证键的顺序。

If they are entered in the same order, this approach would work most of the time, but it would not be reliable.

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

Also, it would return false for objects that were deeply equal, but whose keys were entered in a different order:

同样,如果对象非常相等,但其键按不同的顺序输入,则返回false:

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

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

#2


5  

I realize it's an old question, but I just wanted to add a bit more to the answers, since someone might otherwise walk away from this page mistakenly thinking that using JSON.stringify for comparisons/cloning will work without issue so long as it isn't used to compare/clone objects whose members are unordered. (To be fair to the accepted answer, they shouldn't walk away thinking that; it says, "If [the members] are entered in the same order, this approach would work most of the time.")

我意识到这是一个古老的问题,但我只是想在答案中增加一点,否则有人可能会错误地认为使用JSON。用于比较/克隆的stringify只要不用于比较/克隆成员无序的对象,就不会有问题。(公平地说,他们不应该在离开的时候认为;它说,“如果(成员)以相同的顺序输入,这种方法将在大多数时候起作用。”

Code probably illustrates the potential hiccups best:

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

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}

These are quirks that can cause trouble even when ordering isn't an issue (which, as others have said, it can be). It's probably not likely in most cases that these quirks will rear their ugly heads, but it's good to be aware of them, since they could result in some really hard to find bugs.

这些怪癖即使在订购不是问题的时候也会引起麻烦(正如其他人所说,这是可能的)。在大多数情况下,这些怪癖不太可能长出丑陋的脑袋,但最好注意它们,因为它们可能会导致一些很难发现的bug。

#3


2  

As long as the key-value pairs are always in the same order, yes, you can use stringify to compare using the deep equals operator (===).

只要键值对始终处于相同的顺序,那么可以使用stringify来比较使用deep equals操作符(==)。

#1


10  

JavaScript does not guarantee the order of keys.

JavaScript不保证键的顺序。

If they are entered in the same order, this approach would work most of the time, but it would not be reliable.

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

Also, it would return false for objects that were deeply equal, but whose keys were entered in a different order:

同样,如果对象非常相等,但其键按不同的顺序输入,则返回false:

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

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

#2


5  

I realize it's an old question, but I just wanted to add a bit more to the answers, since someone might otherwise walk away from this page mistakenly thinking that using JSON.stringify for comparisons/cloning will work without issue so long as it isn't used to compare/clone objects whose members are unordered. (To be fair to the accepted answer, they shouldn't walk away thinking that; it says, "If [the members] are entered in the same order, this approach would work most of the time.")

我意识到这是一个古老的问题,但我只是想在答案中增加一点,否则有人可能会错误地认为使用JSON。用于比较/克隆的stringify只要不用于比较/克隆成员无序的对象,就不会有问题。(公平地说,他们不应该在离开的时候认为;它说,“如果(成员)以相同的顺序输入,这种方法将在大多数时候起作用。”

Code probably illustrates the potential hiccups best:

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

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}

These are quirks that can cause trouble even when ordering isn't an issue (which, as others have said, it can be). It's probably not likely in most cases that these quirks will rear their ugly heads, but it's good to be aware of them, since they could result in some really hard to find bugs.

这些怪癖即使在订购不是问题的时候也会引起麻烦(正如其他人所说,这是可能的)。在大多数情况下,这些怪癖不太可能长出丑陋的脑袋,但最好注意它们,因为它们可能会导致一些很难发现的bug。

#3


2  

As long as the key-value pairs are always in the same order, yes, you can use stringify to compare using the deep equals operator (===).

只要键值对始终处于相同的顺序,那么可以使用stringify来比较使用deep equals操作符(==)。