694 votos

¿Cómo se determina la igualdad de dos objetos de JavaScript?

Un operador de igualdad estricta le dirá si el objeto dos tipos son iguales, sin embargo, es hay alguna manera de saber si dos objetos son iguales, tanto como el valor de código hash en Java?

Esto es similar a esta pregunta, pero requiere más académico respuesta:

http://stackoverflow.com/questions/194846/is-there-any-kind-of-hashcode-function-in-javascript

El escenario anterior demuestra por qué sería necesario para tener uno, y me pregunto si hay algún equivalente de la solución.

517voto

CoolAJ86 Puntos 19341

¿Por qué reinventar la rueda? Dar underscore.js un intento. Tiene un número de funciones que necesita, tales como isEqual().

http://lodash.com/docs#isEqual

_.isEqual(object, other);

Es la fuerza bruta comprobar cada valor de la clave - como el resto de los ejemplos en esta página - el uso de es5 y nativo de optimizaciones si están disponibles en el navegador.

Nota: Anteriormente esta respuesta recomendada de subrayado, pero lodash ha hecho un mejor trabajo para llegar errores corregidos y resolución de los problemas con la consistencia.

179voto

AnthonyWJones Puntos 122520

La respuesta corta

La respuesta simple es que no hay ningún medio genérico para determinar que un objeto es igual a otro en el sentido de que significa. La excepción es cuando usted está estrictamente el pensamiento de un objeto que se está abreviado.

El tiempo de respuesta

El concepto es el de un método Equals, que compara dos instancias diferentes de un objeto para indicar si en un valor de nivel son iguales. Sin embargo, no es hasta el tipo específico para definir cómo un Equals método debe ser implementado. Un proceso iterativo de la comparación de los atributos que tienen valores primitivos puede no ser suficiente, bien puede atributos que no son considerados como parte del valor del objeto. Por ej.,

 function MyClass(a, b)
 {
     var c;
     this.getCLazy = function() {
         if (c === undefined) c = a * b // imagine * is really expensive
         return c;
     }
  }

En este caso c no es realmente importante para determinar si cualquiera de las dos instancias de Miclase son iguales, sólo a y b son importantes. En algunos casos, la c podría variar entre instancias y sin embargo no ser significativo a la hora de comparar.

Nota este problema se aplica cuando los miembros pueden ser también instancias de un tipo y cada uno de estos estarían obligados a contar con medios para determinar la igualdad.

Para complicar aún más las cosas es que en Javascript de la distinción entre los datos y el método es borrosa.

Un objeto puede hacer referencia a un método que es llamado como un controlador de eventos, esto probablemente no será considerado como parte de su 'valor'. Mientras que otro objeto que bien puede ser asignado a una función que realiza una importante cálculo y lo que hace este caso diferente de los demás simplemente porque hace referencia a una función diferente.

¿Qué acerca de un objeto que tiene uno de sus actuales prototipo métodos sustituir por otra función. Podría todavía ser considerado igual a otra instancia que de otra manera idéntica? Esa pregunta sólo puede ser contestada en cada caso específico para cada tipo.

Como se dijo anteriormente, la excepción sería estrictamente abreviado objeto. En cuyo caso la única opción lógica es un proceso iterativo y recursivo comparación de cada uno de los miembros. Incluso entonces uno se tiene que preguntar ¿qué es el " valor " de una función?

163voto

Daniel X Moore Puntos 6026

El operador de igualdad predeterminado para los objetos en JavaScript produce cierto cuando se refieren a la misma ubicación en la memoria.

 var x = {};
var y = {};
var z = x;

x === y; // => false
x === z; // => true
 

Si usted requiere un operador de igualdad diferente que tendrá que añadir un equals(other) método, o algo parecido a sus clases y los específicos de su dominio del problema determinará qué significa eso exactamente.

He aquí un ejemplo de tarjeta de juego:

 function Card(rank, suit) {
  this.rank = rank;
  this.suit = suit;
  this.equals = function(other) {
     return other.rank == this.rank && other.suit == this.suit;
  };
}

var queenOfClubs = new Card(12, "C");
var kingOfSpades = new Card(13, "S");

queenOfClubs.equals(kingOfSpades); // => false
kingOfSpades.equals(new Card(13, "S")); // => true
 

53voto

Joel Anair Puntos 8561

Si está utilizando una biblioteca JSON, puede codificar cada objeto como JSON, a continuación, comparar las cadenas resultantes para la igualdad.

 var obj1={test:"value"};
var obj2={test:"value2"};

alert(JSON.encode(obj1)===JSON.encode(obj2));
 

NOTA: Si bien esta respuesta funcionará en muchos casos, ya que varias personas han señalado en los comentarios es problemático para una variedad de razones. En prácticamente todos los casos usted querrá encontrar una solución más robusta.

22voto

Ates Goral Puntos 47670

Si usted tiene una profunda función de copia a mano, puede utilizar el siguiente truco que todavía uso JSON.stringify mientras que coinciden con el orden de las propiedades:

function equals(obj1, obj2) {
    function _equals(obj1, obj2) {
        return JSON.stringify(obj1)
            === JSON.stringify($.extend(true, {}, obj1, obj2));
    }
    return _equals(obj1, obj2) && _equals(obj2, obj1);
}

Demostración: http://jsfiddle.net/CU3vb/3/

Justificación:

Desde que las propiedades de obj1 son copiados al clon de uno por uno, su orden en el clon va a ser preservado. Y cuando las propiedades de obj2 son copiados a la clonación, puesto que las propiedades ya existentes en obj1 simplemente se sobrescriben, de sus órdenes en el clon va a ser preservado.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X