19

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

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?

4

4 回答 4

26

JavaScript 不保证键的顺序。

如果它们以相同的顺序输入,这种方法大部分时间都可以工作,但它并不可靠。

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

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

JSON.stringify({ b: 2, a: 1}) === "{"b":2,"a":1}"
于 2014-09-27T17:53:36.840 回答
14

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

即使订购不是问题(正如其他人所说,它可能是),这些怪癖也会引起麻烦。在大多数情况下,这些怪癖可能不太可能会抬起他们丑陋的脑袋,但了解它们是件好事,因为它们可能会导致一些很难找到的错误。

于 2016-03-15T13:03:35.120 回答
0

我编写了这个函数来深入比较任何对象数组或值:如果需要,可以使用它:) 我用非常大的对象样本测试了它,对象和数组中的条目顺序也是随机的。

function c(x,y) {
    if(!x&&!y)return!0;if(!x||!y)return!1;if(typeof(x)
    !=typeof(y))return!1;if(x instanceof Array){if(
    x.length!=y.length)return!1;var f=[];for(var i=0;
    i<x.length;i++){if(!c(x[i],y[i]))f.push(i)}var g=
    [...f];for(const i of f){let r=!1;for(const j of g){if(
    c(x[i],y[j])){g.splice(g.indexOf(j),1);r++;break}}if(!r)
    return!1}return!0}else if(x instanceof Object){var e1=
    Object.entries(x);try{return c(e1,r(Object.entries(y),
    e1))}catch(e){return!1}}else{return x===y}function r(
    u,v){var a=[];if(u.length!=v.length)return u;for(
    var i=0;i<v.length;i++){a.push(m(u,v[i][0]))}return a}
    function m(a,k){for(var i=0;i<a.length;i++){
    if(a[i][0]===k)return[a[i][0],a[i][1]]}throw 0;}
}
于 2022-02-04T14:26:09.610 回答
-1

只要键值对始终处于相同的顺序,是的,您可以使用 stringify 使用深度等于运算符 (===) 进行比较。

于 2013-03-13T02:59:26.297 回答