Un operador de igualdad estricta le dirá si dos tipos de objetos son iguales. Sin embargo, ¿hay alguna manera de saber si dos objetos son iguales, como el valor del código hash en Java?
Pregunta de desbordamiento de pila ¿Hay algún tipo de función hashCode en JavaScript? es similar a esta pregunta, pero requiere una respuesta más académica. El escenario anterior demuestra por qué sería necesario tener uno, y me pregunto si hay una solución equivalente .
javascript
object
equals
hashcode
Comunidad
fuente
fuente
a.hashCode() == b.hashCode()
no , no implica quea
sea igualb
. Es una condición necesaria, no suficiente.Respuestas:
La respuesta corta
La respuesta simple es: No, no hay medios genéricos para determinar que un objeto es igual a otro en el sentido que quiere decir. La excepción es cuando está estrictamente pensando que un objeto no tiene tipo.
La respuesta larga
El concepto es el de un método Equals que compara dos instancias diferentes de un objeto para indicar si son iguales en un nivel de valor. Sin embargo, depende del tipo específico definir cómo un
Equals
se debe implementar método. Una comparación iterativa de atributos que tienen valores primitivos puede no ser suficiente, bien puede haber atributos que no deben considerarse parte del valor del objeto. Por ejemplo,En este caso anterior,
c
no es realmente importante determinar si dos instancias de MyClass son iguales, soloa
y sib
son importantes. En algunos casos,c
puede variar entre instancias y, sin embargo, no ser significativo durante la comparación.Tenga en cuenta que este problema se aplica cuando los miembros también pueden ser instancias de un tipo y cada uno de ellos debería tener un medio para determinar la igualdad.
Lo que complica aún más las cosas es que en JavaScript la distinción entre datos y método es borrosa.
Un objeto puede hacer referencia a un método que se llamará como un controlador de eventos, y esto probablemente no se considerará parte de su "estado de valor". Mientras que a otro objeto se le puede asignar una función que realiza un cálculo importante y, por lo tanto, hace que esta instancia sea diferente de las demás simplemente porque hace referencia a una función diferente.
¿Qué pasa con un objeto que tiene uno de sus métodos prototipo existentes anulados por otra función? ¿Podría aún considerarse igual a otra instancia que de lo contrario es idéntico? Esa pregunta solo puede responderse en cada caso específico para cada tipo.
Como se indicó anteriormente, la excepción sería un objeto estrictamente sin tipo. En cuyo caso, la única opción sensata es una comparación iterativa y recursiva de cada miembro. Incluso entonces, uno tiene que preguntarse cuál es el "valor" de una función.
fuente
_.isEqual(obj1, obj2);
.equals
método no es trivial, por lo que existe un tema dedicado en Java efectivo .javascript equality object
, obtuve tl; la respuesta del Dr., tomó una frase del comentario de @chovy. graciasangular.equals
¿Por qué reinventar la rueda? Dale una oportunidad a Lodash . Tiene varias funciones imprescindibles , como isEqual () .
Verificará la fuerza bruta de cada valor clave, al igual que los otros ejemplos en esta página, utilizando ECMAScript 5 y optimizaciones nativas si están disponibles en el navegador.
Nota: Anteriormente, esta respuesta recomendaba Underscore.js , pero lodash ha hecho un mejor trabajo al corregir los errores y abordar los problemas con coherencia.
fuente
El operador de igualdad predeterminado en JavaScript para Objetos produce verdadero cuando se refieren a la misma ubicación en la memoria.
Si necesita un operador de igualdad diferente, deberá agregar un
equals(other)
método, o algo similar a sus clases, y los detalles del dominio de su problema determinarán qué significa exactamente eso.Aquí hay un ejemplo de naipes:
fuente
{x:1, y:2}
! =={y:2, x:1}
Si está trabajando en AngularJS , la
angular.equals
función determinará si dos objetos son iguales. En uso de Ember.jsisEqual
.angular.equals
- Consulte los documentos o la fuente para obtener más información sobre este método. También hace una comparación profunda en matrices.isEqual
: consulte los documentos o la fuente para obtener más información sobre este método. No hace una comparación profunda en las matrices.fuente
Esta es mi versión Está utilizando la nueva característica Object.keys que se introduce en ES5 e ideas / pruebas de + , + y + :
fuente
objectEquals([1,2,undefined],[1,2])
regresatrue
objectEquals([1,2,3],{0:1,1:2,2:3})
también regresatrue
, por ejemplo, no hay verificación de tipo, solo verificación de clave / valor.objectEquals(new Date(1234),1234)
regresatrue
Si está utilizando una biblioteca JSON, puede codificar cada objeto como JSON y luego comparar las cadenas resultantes para la igualdad.
NOTA: Si bien esta respuesta funcionará en muchos casos, como varias personas han señalado en los comentarios, es problemática por varias razones. En casi todos los casos, querrás encontrar una solución más robusta.
fuente
deepEqual
Implementación funcional corta :Edición : versión 2, utilizando la sugerencia de jib y las funciones de flecha ES6:
fuente
reduce
conevery
para simplificar.Object.keys(x).every(key => deepEqual(x[key], y[key]))
.: (x === y)
con: (x === y && (x != null && y != null || x.constructor === y.constructor))
¿Estás tratando de probar si dos objetos son iguales? es decir: sus propiedades son iguales?
Si este es el caso, probablemente habrás notado esta situación:
puede que tengas que hacer algo como esto:
Obviamente, esa función podría funcionar con bastante optimización y la capacidad de realizar una verificación profunda (para manejar objetos anidados:
var a = { foo : { fu : "bar" } }
), pero se entiende la idea.Como FOR señaló, puede que tenga que adaptar esto para sus propios fines, por ejemplo: diferentes clases pueden tener diferentes definiciones de "igual". Si solo está trabajando con objetos simples, lo anterior puede ser suficiente, de lo contrario, una
MyClass.equals()
función personalizada puede ser el camino a seguir.fuente
Si tiene a mano una función de copia profunda, puede utilizar el siguiente truco para seguir utilizando
JSON.stringify
el orden de propiedades:Demostración: http://jsfiddle.net/CU3vb/3/
Razón fundamental:
Como las propiedades de
obj1
se copian en el clon una por una, se preservará su orden en el clon. Y cuando las propiedades deobj2
se copian en el clon, dado que las propiedades ya existentesobj1
simplemente se sobrescribirán, se preservarán sus órdenes en el clon.fuente
En Node.js, puede usar su nativo
require("assert").deepStrictEqual
. Más información: http://nodejs.org/api/assert.htmlPor ejemplo:
Otro ejemplo que devuelve
true
/ enfalse
lugar de devolver errores:fuente
Chai
tiene esta característica también En su caso, utilizará:var foo = { a: 1 }; var bar = { a: 1 }; expect(foo).to.deep.equal(bar); // true;
error.name
en"AssertionError [ERR_ASSERTION]"
. En este caso, reemplazaría la declaración if conif (error.code === 'ERR_ASSERTION') {
.deepStrictEqual
era el camino a seguir. Había estado destrozándome el cerebro tratando de entender por quéstrictEqual
no funcionaba. Fantástico.Soluciones más simples y lógicas para comparar todo, como objetos, matrices, cadenas, int ...
JSON.stringify({a: val1}) === JSON.stringify({a: val2})
Nota:
val1
yval2
con su objetofuente
JSON.stringify
que un reordenamiento alfabético? (Que no puedo encontrar documentado .)Utilizo esta
comparable
función para producir copias de mis objetos que son comparables a JSON:Es útil en las pruebas (la mayoría de los marcos de prueba tienen una
is
función). P.ejSi se detecta una diferencia, las cadenas se registran, haciendo que las diferencias sean visibles:
fuente
Heres es una solución en ES6 / ES2015 utilizando un enfoque de estilo funcional:
demo disponible aquí
fuente
No sé si alguien ha publicado algo similar a esto, pero aquí hay una función que hice para verificar la igualdad de objetos.
Además, es recursivo, por lo que también puede verificar la igualdad profunda, si así lo llamas.
fuente
Para aquellos de ustedes que usan NodeJS, existe un método conveniente llamado
isDeepStrictEqual
en la biblioteca Util nativa que puede lograr esto.https://nodejs.org/api/util.html#util_util_isdeepstrictequal_val1_val2
fuente
ES6: El código mínimo que podría hacer, es este. Realiza una comparación profunda recursivamente mediante la cadena de todos los objetos, la única limitación es que no se comparan métodos ni símbolos.
fuente
puede usar
_.isEqual(obj1, obj2)
desde la biblioteca underscore.js.Aquí hay un ejemplo:
Consulte la documentación oficial desde aquí: http://underscorejs.org/#isEqual
fuente
Suponiendo que el orden de las propiedades en el objeto no cambia.
JSON.stringify () funciona para ambos tipos de objetos profundos y no profundos, no muy seguro de los aspectos de rendimiento:
fuente
Una solución simple a este problema que muchas personas no se dan cuenta es ordenar las cadenas JSON (por carácter). Esto también suele ser más rápido que las otras soluciones mencionadas aquí:
Otra cosa útil sobre este método es que puede filtrar las comparaciones pasando una función "reemplazadora" a las funciones JSON.stringify ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON / stringify # Example_of_using_replacer_parameter ). Lo siguiente solo comparará todas las claves de objetos que se denominan "derp":
fuente
areEqual({a: 'b'}, {b: 'a'})
consiguetrue
entonces?Solo quería contribuir con mi versión de comparación de objetos utilizando algunas características de es6. No tiene en cuenta un pedido. Después de convertir todos los if / else's a ternary, he venido con lo siguiente:
fuente
Al necesitar una función de comparación de objetos más genérica que la publicada, preparé lo siguiente. Crítica apreciada ...
fuente
Object.prototype
: en la gran mayoría de los casos no se recomienda (las adiciones aparecen en todos para ... en bucles, por ejemplo). Tal vez considerarObject.equals = function(aObj, bObj) {...}
?Si está comparando objetos JSON, puede usar https://github.com/mirek/node-rus-diff
Uso:
Si dos objetos son diferentes,
{$rename:{...}, $unset:{...}, $set:{...}}
se devuelve un objeto similar compatible con MongoDB .fuente
Me enfrenté al mismo problema y decidí escribir mi propia solución. Pero debido a que también quiero comparar matrices con objetos y viceversa, diseñé una solución genérica. Decidí agregar las funciones al prototipo, pero uno puede reescribirlas fácilmente en funciones independientes. Aquí está el código:
Este algoritmo se divide en dos partes; La función igual en sí misma y una función para encontrar el índice numérico de una propiedad en una matriz / objeto. La función de búsqueda solo es necesaria porque indexof solo encuentra números y cadenas y no objetos.
Uno puede llamarlo así:
La función devuelve verdadero o falso, en este caso verdadero. El algoritmo als permite la comparación entre objetos muy complejos:
El ejemplo superior devolverá verdadero, incluso aunque las propiedades tengan un orden diferente. Un pequeño detalle a tener en cuenta: este código también busca el mismo tipo de dos variables, por lo que "3" no es lo mismo que 3.
fuente
Veo respuestas de código de espagueti. Sin usar ninguna biblioteca de terceros, esto es muy fácil.
En primer lugar, clasifique los dos objetos por sus nombres clave.
Luego, simplemente use una cadena para compararlos.
fuente
Aconsejaría contra el hash o la serialización (como sugiere la solución JSON). Si necesita probar si dos objetos son iguales, entonces necesita definir qué significa igual. Puede ser que todos los miembros de datos en ambos objetos coincidan, o puede ser que las ubicaciones de la memoria coincidan (lo que significa que ambas variables hacen referencia al mismo objeto en la memoria), o que solo un miembro de datos en cada objeto debe coincidir.
Recientemente desarrollé un objeto cuyo constructor crea una nueva identificación (comenzando desde 1 e incrementando en 1) cada vez que se crea una instancia. Este objeto tiene una función isEqual que compara ese valor de identificación con el valor de identificación de otro objeto y devuelve verdadero si coinciden.
En ese caso, definí "igual" como el significado de los valores de id. Dado que cada instancia tiene una identificación única, esto podría usarse para forzar la idea de que los objetos coincidentes también ocupan la misma ubicación de memoria. Aunque eso no es necesario.
fuente
Es útil considerar dos objetos iguales si tienen los mismos valores para todas las propiedades y recursivamente para todos los objetos y matrices anidados. También considero iguales los siguientes dos objetos:
Del mismo modo, las matrices pueden tener elementos "faltantes" y elementos indefinidos. También los trataría igual:
Una función que implementa esta definición de igualdad:
Código fuente (incluidas las funciones auxiliares, generalType y uniqueArray): Prueba de unidad y Test Runner aquí .
fuente
Estoy haciendo los siguientes supuestos con esta función:
Esto debe tratarse como una demostración de una estrategia simple.
fuente
Esta es una adición para todo lo anterior, no un reemplazo. Si necesita hacer una comparación rápida de objetos poco profundos sin necesidad de verificar casos recursivos adicionales. Aquí hay una foto.
Esto se compara para: 1) Igualdad de número de propiedades propias, 2) Igualdad de nombres clave, 3) si bCompareValues == verdadero, Igualdad de los valores de propiedad correspondientes y sus tipos (triple igualdad)
fuente
Para comparar claves para instancias de objeto de pares clave / valor simples, utilizo:
Una vez que se comparan las claves, un simple
for..in
bucle adicional es suficiente.La complejidad es O (N * N) con N es el número de claves.
Espero / adivino que los objetos que defino no tendrán más de 1000 propiedades ...
fuente
Sé que esto es un poco viejo, pero me gustaría agregar una solución que se me ocurrió para este problema. Tenía un objeto y quería saber cuándo cambiaron sus datos. "algo similar a Object.observe" y lo que hice fue:
Esto aquí puede duplicarse y crear otro conjunto de matrices para comparar los valores y las claves. Es muy simple porque ahora son matrices y devolverán falso si los objetos tienen tamaños diferentes.
fuente
false
, porque las matrices no se comparan por valor, por ejemplo[1,2] != [1,2]
.