Comparar objetos en Angular

79

¿Es posible hacer una comparación "profunda" de dos objetos en Angular? Lo que me gustaría hacer es comparar cada par clave / valor. Por ejemplo:

Objeto 1

{
   key1: "value1",
   key2: "value2",
   key3: "value3"
}

Objeto 2

{
   key1: "value1",
   key2: "newvalue",
   key3: "value3" 
}

Lo que necesito es que la comparación falle, ya que solo uno de los pares clave / valor es diferente. En otras palabras, TODOS los pares clave / valor deben coincidir exactamente o fallarán. ¿Es esto algo que ya está integrado en Angular? Estoy seguro de que podría escribir mi propio servicio si realmente lo necesitara, pero esperaba que ya estuviera integrado. Similar a angular.equals.

selanac82
fuente

Respuestas:

205

Para comparar dos objetos puedes usar:

angular.equals(obj1, obj2)

Hace una comparación profunda y no depende del orden de las teclas Ver AngularJS DOCS y una pequeña Demo

var obj1 = {
  key1: "value1",
  key2: "value2",
  key3: {a: "aa", b: "bb"}
}

var obj2 = {
  key2: "value2",
  key1: "value1",
  key3: {a: "aa", b: "bb"}
}

angular.equals(obj1, obj2) //<--- would return true
klode
fuente
6
Tenga en cuenta que angular.equals prueba la identidad, no la igualdad . TL; DR:angular.equals( { id: "12" }, { id: 12 } ) // is false
bobjones
@bobjones angular.equals devuelve verdadero según la identidad O la igualdad profunda, por lo que su ejemplo propuesto devolvería verdadero. consulte la documentación de angular.equals , específicamente Dos objetos o valores se consideran equivalentes si al menos uno de los siguientes es verdadero
tommyTheHitMan
5
@tommyTheHitMan: bobjones ejemplo rendimientos false, ya que, sobre la base de la identidad, "12"===12 // is false. Pruébelo.
klode
Y si necesita un objeto de diferencia para rastrear el historial de retrocesos, vea esto ... gist.github.com/katowulf/6193808
Mark
4
Una nota rápida: angular.equals () ignora todas las propiedades que comienzan con $ y todas las propiedades cuyos valores son funciones, cuando ambos argumentos son objetos.
im1dermike
24

Suponiendo que el orden es el mismo en ambos objetos, ¡solo stringifyen ambos y compare!

JSON.stringify(obj1) == JSON.stringify(obj2);
tymeJV
fuente
14
angular.equals (obj1, obj2) también debería funcionar. No depende del orden de las claves y es profundo (se llama recursivamente) code.angularjs.org/1.2.0/docs/api/angular.equals
klode
4
¡Sería una muy mala suposición!
principio holográfico
1
angular.toJsontambién eliminaría las $$ hashKeys
5

Un poco tarde en este hilo. angular.equals hace una verificación profunda, sin embargo, ¿alguien sabe por qué se comporta de manera diferente si uno de los miembros contiene "$" en el prefijo?

Puede probar esta demostración con la siguiente entrada

var obj3 = {}
obj3.a=  "b";
obj3.b={};
obj3.b.$c =true;

var obj4 = {}
obj4.a=  "b";
obj4.b={};
obj4.b.$c =true;

angular.equals(obj3,obj4);
KM.
fuente
4
De la documentación de Angular: "Durante una comparación de propiedades, las propiedades del tipo de función y las propiedades con nombres que comienzan con $ se ignoran". docs.angularjs.org/api/ng/function/angular.equals
sonicwizard
2

Sé que es una respuesta un poco tardía, pero acabo de perder alrededor de media hora depurando la causa de esto, podría ahorrarle a alguien algo de tiempo.

TENGA EN CUENTA, si usa angular.equals()en objetos que tienen propiedad obj.$something (el nombre de la propiedad comienza con $), esas propiedades se ignorarán en comparación.

Ejemplo:

var obj1 = {
  $key0: "A",
  key1: "value1",
  key2: "value2",
  key3: {a: "aa", b: "bb"}
}

var obj2 = {
  $key0: "B"
  key2: "value2",
  key1: "value1",
  key3: {a: "aa", b: "bb"}
}

angular.equals(obj1, obj2) //<--- would return TRUE (despite it's not true)
DanteTheSmith
fuente