对象/数组比较深 [英] Deep comparison of objects/arrays

查看:238
本文介绍了对象/数组比较深的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:结果
  <一href=\"http://stackoverflow.com/questions/201183/how-do-you-determine-equality-for-two-javascript-objects\">How你确定平等两个JavaScript对象?结果
  在JavaScript中 对象比较

Possible Duplicate:
How do you determine equality for two JavaScript objects?
Object comparison in JavaScript

所以,如果我有两个数组或对象,并希望对它们进行比较,如

so if I have two arrays or objects and want to compare them, such as

object1 = [
 { shoes:
   [ 'loafer', 'penny' ]
  },
  { beers:
     [ 'budweiser', 'busch' ]
  }
]

object2 = [
 { shoes:
   [ 'loafer', 'penny' ]
  },
  { beers:
     [ 'budweiser', 'busch' ]
  }
]

object1 == object2 // false

如果你得到来自服务器的响应,并试图看它是否改变了这种可恼人

this can be annoying if you're getting a response from a server and trying to see if it's changed

推荐答案

更新:的结果
为了应对周边原有的建议(2比较JSON字符串)的意见和忧虑,可以使用此功能:

Update:
In response to the comments and worries surrounding the original suggestion (comparing 2 JSON strings), you could use this function:

function compareObjects(o, p)
{
    var i,
        keysO = Object.keys(o).sort(),
        keysP = Object.keys(p).sort();
    if (keysO.length !== keysP.length)
        return false;//not the same nr of keys
    if (keysO.join('') !== keysP.join(''))
        return false;//different keys
    for (i=0;i<keysO.length;++i)
    {
        if (o[keysO[i]] instanceof Array)
        {
            if (!(p[keysO[i]] instanceof Array))
                return false;
            //if (compareObjects(o[keysO[i]], p[keysO[i]] === false) return false
            //would work, too, and perhaps is a better fit, still, this is easy, too
            if (p[keysO[i]].sort().join('') !== o[keysO[i]].sort().join(''))
                return false;
        }
        else if (o[keysO[i]] instanceof Date)
        {
            if (!(p[keysO[i]] instanceof Date))
                return false;
            if ((''+o[keysO[i]]) !== (''+p[keysO[i]]))
                return false;
        }
        else if (o[keysO[i]] instanceof Function)
        {
            if (!(p[keysO[i]] instanceof Function))
                return false;
            //ignore functions, or check them regardless?
        }
        else if (o[keysO[i]] instanceof Object)
        {
            if (!(p[keysO[i]] instanceof Object))
                return false;
            if (o[keysO[i]] === o)
            {//self reference?
                if (p[keysO[i]] !== p)
                    return false;
            }
            else if (compareObjects(o[keysO[i]], p[keysO[i]]) === false)
                return false;//WARNING: does not deal with circular refs other than ^^
        }
        if (o[keysO[i]] !== p[keysO[i]])//change !== to != for loose comparison
            return false;//not the same value
    }
    return true;
}

但是,在许多情况下,它不必是困难IMO:

But in many cases, it needn't be that difficult IMO:

JSON.stringify(object1) === JSON.stringify(object2);

如果字符串化的对象是相同的,它们的值都是一样的。

为了完整起见: JSON 简单地忽略的功能(当然,删除它们放在一起)。它的意思重新present的数据的,不是的功能的。

试图比较仅包含的功能将导致 2的物体真实

If the stringified objects are the same, their values are alike.
For completeness' sake: JSON simply ignores functions (well, removes them all together). It's meant to represent Data, not functionality.
Attempting to compare 2 objects that contain only functions will result in true:

JSON.stringify({foo: function(){return 1;}}) === JSON.stringify({foo: function(){ return -1;}});
//evaulutes to:
'{}' === '{}'
//is true, of course

有关的对象/功能深度比较,你将不得不求助于库或编写自己的功能,并且克服了事实,JS对象都是引用,所以比较时 01 === OB2 如果两个变量指向同一个对象时,它只会返回true ...

For deep-comparison of objects/functions, you'll have to turn to libs or write your own function, and overcome the fact that JS objects are all references, so when comparing o1 === ob2 it'll only return true if both variables point to the same object...

作为一个@-J在评论中指出:

As @a-j pointed out in the comment:

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

,因为这两个字符串化调用产生{一:1,B:2}分别是{b:2,1}。至于这是为什么,你需要了解Chrome的V8引擎的内部结构。我不是专家,没有考虑太多的细节,这里就是它归结为:

is false, as both stringify calls yield "{"a":1,"b":2}" and "{"b":2,"a":1}" respectively. As to why this is, you need to understand the internals of chrome's V8 engine. I'm not an expert, and without going into too much detail, here's what it boils down to:

在每次修改时所创建的每一个对象,并且,V8创建一个新的隐藏的C ++类(差不多)。如果对象X有一个属性 A ,另一个对象具有相同的属性,这两个JS对象将引用一个隐藏的类,它从一个共享的隐藏类,定义这个属性<继承code> A 。如果两个对象都共享相同的基本属性,然后将他们全部引用相同的隐藏类和 JSON.stringify 将工作在这两个对象完全相同。这是在V8的内部给定(更多细节<一个href=\"http://stackoverflow.com/questions/21382811/does-chrome-retain-each-objects-constructor/21551377#21551377\">here,如果你有兴趣)。

Each object that is created, and each time it is modified, V8 creates a new hidden C++ class (sort of). If object X has a property a, and another object has the same property, both these JS objects will reference a hidden class that inherits from a shared hidden class that defines this property a. If two objects all share the same basic properties, then they will all reference the same hidden classes, and JSON.stringify will work exactly the same on both objects. That's a given (More details on V8's internals here, if you're interested).

但是,在由-j中指出的例子中,两个对象不同字符串化。怎么来的?好吧,简单地说,这些对象从来没有在同一时间存在:

However, in the example pointed out by a-j, both objects are stringified differently. How come? Well, put simply, these objects never exist at the same time:

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

这是一个函数调用,需要解决的结果值才可以比较右手操作的前pression。第二个对象是面值不上台面呢。结果
对象字符串化,并且exoression被解析为字符串常量。对象常量不被任何地方引用被标记为垃圾回收。结果
在此之后,右手操作数(在 JSON.stringify({B:2,1})前pression)得到同样的待遇。

This is a function call, an expression that needs to be resolved to the resulting value before it can be compared to the right-hand operand. The second object literal isn't on the table yet.
The object is stringified, and the exoression is resolved to a string constant. The object literal isn't being referenced anywhere and is flagged for garbage collection.
After this, the right hand operand (the JSON.stringify({b: 2, a: 1}) expression) gets the same treatment.

所有罚款和花花公子,但是还需要考虑的是,JS引擎现在远比以前要更复杂。再次,我不是专家V8,但我认为它合理的,A-J的片段被大量优化,在那code优化为:

All fine and dandy, but what also needs to be taken into consideration is that JS engines now are far more sophisticated than they used to be. Again, I'm no V8 expert, but I think its plausible that a-j's snippet is being heavily optimized, in that the code is optimized to:

"{"b":2,"a":1}" === "{"a":1,"b":2}"

从本质上省略了 JSON.stringify 调用所有在一起,只是增加在正确的地方引号。也就是说,毕竟,很多更有效率。

Essentially omitting the JSON.stringify calls all together, and just adding quotes in the right places. That is, after all, a lot more efficient.

这篇关于对象/数组比较深的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆