Tengo 2 objetos anidados que son diferentes y necesito saber si tienen una diferencia en una de sus propiedades anidadas.
var a = {};
var b = {};
a.prop1 = 2;
a.prop2 = { prop3: 2 };
b.prop1 = 2;
b.prop2 = { prop3: 3 };
El objeto podría ser mucho más complejo con más propiedades anidadas. Pero este es un buen ejemplo. Tengo la opción de usar funciones recursivas o algo con lodash ...
javascript
lodash
JLavoie
fuente
fuente
_.isEqual(value, other)
Realiza una comparación profunda entre dos valores para determinar si son equivalentes. lodash.com/docs#isEqualRespuestas:
Es una solución fácil y elegante de usar
_.isEqual
, que realiza una comparación profunda:Sin embargo, esta solución no muestra qué propiedad es diferente.
http://jsfiddle.net/bdkeyn0h/
fuente
_.isEqual
puede ser bastante complicado. Si copia el objeto y cambia algunos valores allí, seguirá siendo verdadero, porque la referencia es la misma. Así que uno debe tener cuidado al usar esta función.Si necesita saber qué propiedades son diferentes, use reduce () :
fuente
_.reduce(a, (result, value, key) => _.isEqual(value, b[key]) ? result : result.concat(key), [])
para una solución ES6 de una línealet edited = _.reduce(a, function(result, value, key) { return _.isEqual(value, b[key]) ? result : result.concat( { [key]: value } ); }, []);
Para cualquiera que se encuentre con este hilo, aquí hay una solución más completa. Comparará dos objetos y le dará la clave de todas las propiedades que están solo en objeto1 , solo en objeto2 , o están en objeto1 y objeto2 pero tienen valores diferentes :
Aquí hay un ejemplo de salida:
Si no le importan los objetos anidados y desea omitir lodash, puede sustituirlo
_.isEqual
por una comparación de valores normales, por ejemploobj1[key] === obj2[key]
.fuente
Basado en la respuesta de Adam Boduch , escribí esta función que compara dos objetos en el sentido más profundo posible , devolviendo rutas que tienen valores diferentes, así como rutas que faltan en uno u otro objeto.
El código no fue escrito con la eficiencia en mente, y las mejoras en ese sentido son bienvenidas, pero aquí está la forma básica:
Puede probar el código con este fragmento (se recomienda ejecutar en modo de página completa):
Mostrar fragmento de código
fuente
b
usandob.hasOwnProperty(key)
okey in b
, no conb[key] != undefined
. Con la versión anterior que se usabab[key] != undefined
, la función devolvía un diff incorrecto para los objetos que conteníanundefined
, como encompare({disabled: undefined}, {disabled: undefined})
. De hecho, la versión anterior también tenía problemas connull
; puede evitar problemas como ese usando siempre===
y en!==
lugar de==
y!=
.Aquí hay una solución concisa:
fuente
[]
.Para mostrar recursivamente en qué se diferencia un objeto con otro, puede usar _.reduce combinado con _.isEqual y _.isPlainObject . En este caso, puede comparar cómo a es diferente con b o cómo b es diferente con a:
fuente
_.isEqual
Método de uso simple , funcionará para todas las comparaciones ...Entonces, si tienes a continuación:
Si lo hace:
_.isEqual(firstName, otherName);
,volverá verdadero
Y si
const fullName = {firstName: "Alireza", familyName: "Dezfoolian"};
Si lo hace:
_.isEqual(firstName, fullName);
,devolverá falso
fuente
Este código devuelve un objeto con todas las propiedades que tienen un valor diferente y también valores de ambos objetos. Útil para registrar la diferencia.
fuente
Sin el uso de lodash / subrayado, he escrito este código y está funcionando bien para mí para una comparación profunda de object1 con object2
fuente
Comparación profunda utilizando una plantilla de propiedades (anidadas) para verificar
Esto funcionará en la consola. Se podría agregar soporte de matriz si fuera necesario
fuente
Tomé una puñalada del código de Adam Boduch para generar una diferencia profunda: esto no se ha probado por completo, pero las piezas están ahí:
fuente
diff({}, { foo: 'lol', bar: { baz: true }}) // returns []
Como se le preguntó, aquí hay una función de comparación recursiva de objetos. Y un poquito más. Suponiendo que el uso principal de dicha función es la inspección de objetos, tengo algo que decir. La comparación profunda completa es una mala idea cuando algunas diferencias son irrelevantes. Por ejemplo, la comparación ciega profunda en las afirmaciones TDD hace que las pruebas sean innecesariamente frágiles. Por esa razón, me gustaría presentar una diferencia parcial mucho más valiosa . Es un análogo recursivo de una contribución previa a este hilo. Ignora las claves no presentes en un
BDiff permite verificar los valores esperados mientras tolera otras propiedades, que es exactamente lo que desea para la inspección automática . Esto permite construir todo tipo de afirmaciones avanzadas. Por ejemplo:
Volviendo a la solución completa. Construir un diferencial tradicional completo con bdiff es trivial:
Ejecutar la función anterior en dos objetos complejos generará algo similar a esto:
Finalmente, para tener una idea de cómo difieren los valores, es posible que queramos evaluar directamente () la salida de diferencias. Para eso, necesitamos una versión más fea de bdiff que genere rutas sintácticamente correctas:
Eso generará algo similar a esto:
Licencia MIT;)
fuente
Completando la respuesta de Adam Boduch, esta toma en diferencias en las propiedades
fuente
Si solo necesita una comparación de teclas:
fuente
Aquí hay un simple mecanografiado con el comprobador de diferencias profundas Lodash que producirá un nuevo objeto con solo las diferencias entre un objeto antiguo y uno nuevo.
Por ejemplo, si tuviéramos:
el objeto resultante sería:
También es compatible con objetos profundos de varios niveles, para matrices puede necesitar algunos ajustes.
fuente
fuente
===
directamente,{ a: 20 } === { a: 20 }
devolverá falso, porque compara el prototipo. Camino más derecho a comparar objetos principalmente es para envolverlos enJSON.stringify()
_.isEqual(f, s)
? :)f
es un objeto y llega aif (_.isObject(f))
usted, simplemente regrese a través de la función y presione ese punto nuevamente. Lo mismo va paraf (Array.isArray(f)&&Array.isArray(s))
esto se basó en @JLavoie , usando lodash
https://jsfiddle.net/EmilianoBarboza/0g0sn3b9/8/
fuente
solo usando vanilla js
fuente
Para construir sobre la respuesta de Sridhar Gudimela , aquí se actualiza de una manera que hará feliz a Flow:
fuente