Um operador de igualdade estrita dirá se dois tipos de objetos são iguais. No entanto, existe uma maneira de saber se dois objetos são iguais, assim como o valor do código hash em Java?
Pergunta sobre estouro de pilha Existe algum tipo de função hashCode no JavaScript? é semelhante a esta pergunta, mas requer uma resposta mais acadêmica. O cenário acima demonstra por que seria necessário ter um, e eu estou querendo saber se existe alguma solução equivalente .
javascript
object
equals
hashcode
Comunidade
fonte
fonte
a.hashCode() == b.hashCode()
que não implica quea
é igualb
. É uma condição necessária, não suficiente.Respostas:
A resposta curta
A resposta simples é: Não, não há meios genéricos para determinar que um objeto é igual a outro no sentido que você quer dizer. A exceção é quando você está pensando estritamente em um objeto que não possui tipo de letra.
A resposta longa
O conceito é o de um método Equals que compara duas instâncias diferentes de um objeto para indicar se elas são iguais em um nível de valor. No entanto, cabe ao tipo específico definir como um
Equals
método deve ser implementado. Uma comparação iterativa de atributos que possuem valores primitivos pode não ser suficiente, pode haver atributos que não devem ser considerados parte do valor do objeto. Por exemplo,Nesse caso acima,
c
não é realmente importante determinar se duas instâncias do MyClass são iguais, somentea
eb
importantes. Em alguns casos,c
pode variar entre instâncias e ainda não ser significativo durante a comparação.Observe que esse problema se aplica quando os membros também podem ser instâncias de um tipo e cada um deles deveria ter um meio de determinar a igualdade.
O que complica ainda mais é que no JavaScript a distinção entre dados e método é embaçada.
Um objeto pode fazer referência a um método que deve ser chamado como manipulador de eventos, e isso provavelmente não seria considerado parte do seu 'estado do valor'. Enquanto outro objeto pode receber uma função que executa um cálculo importante e, assim, torna essa instância diferente das outras simplesmente porque faz referência a uma função diferente.
E um objeto que possui um dos métodos de protótipo existentes substituído por outra função? Ainda poderia ser considerado igual a outra instância que, de outra forma, seria idêntica? Essa pergunta só pode ser respondida em cada caso específico de cada tipo.
Como afirmado anteriormente, a exceção seria um objeto estritamente sem tipo. Nesse caso, a única escolha sensata é uma comparação iterativa e recursiva de cada membro. Mesmo assim, é preciso perguntar qual é o "valor" de uma função?
fonte
_.isEqual(obj1, obj2);
.equals
método não é trivial, e é por isso que existe um tópico dedicado ao Java Efetivo .javascript equality object
, recebi a resposta do dr., peguei uma frase do comentário @chovy. obrigadoangular.equals
Por que reinventar a roda? Experimente o Lodash . Ele possui várias funções obrigatórias , como isEqual () .
A força bruta verificará cada valor de chave - assim como os outros exemplos nesta página - usando o ECMAScript 5 e otimizações nativas, se estiverem disponíveis no navegador.
Nota: Anteriormente, esta resposta recomendava o Underscore.js , mas o lodash fez um trabalho melhor ao corrigir bugs e solucionar problemas com consistência.
fonte
O operador de igualdade padrão no JavaScript for Objects produz true quando se refere ao mesmo local na memória.
Se você precisar de um operador de igualdade diferente, precisará adicionar um
equals(other)
método ou algo parecido às suas classes e as especificidades do domínio do problema determinarão exatamente o que isso significa.Aqui está um exemplo de baralho:
fonte
{x:1, y:2}
! =={y:2, x:1}
Se você estiver trabalhando no AngularJS , a
angular.equals
função determinará se dois objetos são iguais. No Ember.js, useisEqual
.angular.equals
- Consulte os documentos ou a fonte para obter mais informações sobre este método. Também faz uma comparação profunda em matrizes.isEqual
- consulte a documentação ou a fonte para obter mais informações sobre esse método. Ele não faz uma comparação profunda em matrizes.fonte
Esta é a minha versão. Ele está usando o novo recurso Object.keys introduzido no ES5 e idéias / testes de + , + e + :
fonte
objectEquals([1,2,undefined],[1,2])
retornatrue
objectEquals([1,2,3],{0:1,1:2,2:3})
também retornatrue
- por exemplo, não há verificação de tipo, apenas verificação de chave / valor.objectEquals(new Date(1234),1234)
retornatrue
Se você estiver usando uma biblioteca JSON, poderá codificar cada objeto como JSON e comparar as cadeias resultantes para obter igualdade.
NOTA: Embora essa resposta funcione em muitos casos, como várias pessoas apontaram nos comentários, ela é problemática por vários motivos. Em praticamente todos os casos, você encontrará uma solução mais robusta.
fonte
deepEqual
Implementação funcional curta :Edit : versão 2, usando a sugestão de lança e as funções de seta ES6:
fonte
reduce
porevery
para simplificar.Object.keys(x).every(key => deepEqual(x[key], y[key]))
.: (x === y)
com: (x === y && (x != null && y != null || x.constructor === y.constructor))
Você está tentando testar se dois objetos são iguais? ou seja: suas propriedades são iguais?
Se for esse o caso, você provavelmente já notou esta situação:
você pode ter que fazer algo assim:
Obviamente, essa função poderia ter um pouco de otimização e a capacidade de fazer uma verificação profunda (para manipular objetos aninhados :),
var a = { foo : { fu : "bar" } }
mas você entendeu.Como FOR apontou, você pode ter que adaptar isso para seus próprios propósitos, por exemplo: classes diferentes podem ter definições diferentes de "igual". Se você estiver trabalhando apenas com objetos simples, as opções acima podem ser suficientes, caso contrário, uma
MyClass.equals()
função personalizada pode ser o caminho a percorrer.fonte
Se você tiver uma função de cópia profunda à mão, poderá usar o seguinte truque para continuar usando
JSON.stringify
a ordem das propriedades:Demonstração: http://jsfiddle.net/CU3vb/3/
Fundamentação da petição:
Como as propriedades de
obj1
são copiadas para o clone uma por uma, sua ordem no clone será preservada. E quando as propriedades deobj2
são copiadas para o clone, como as propriedades já existentesobj1
serão simplesmente substituídas, suas ordens no clone serão preservadas.fonte
No Node.js, você pode usar seu nativo
require("assert").deepStrictEqual
. Mais informações: http://nodejs.org/api/assert.htmlPor exemplo:
Outro exemplo que retorna
true
/ emfalse
vez de retornar erros:fonte
Chai
tem esse recurso também. Nesse caso, você usará:var foo = { a: 1 }; var bar = { a: 1 }; expect(foo).to.deep.equal(bar); // true;
error.name
como"AssertionError [ERR_ASSERTION]"
. Nesse caso, eu substituiria a instrução if porif (error.code === 'ERR_ASSERTION') {
.deepStrictEqual
do caminho a seguir. Eu estava destruindo meu cérebro tentando descobrir por questrictEqual
não estava funcionando. Fantástico.Soluções mais simples e lógicas para comparar tudo como objeto, matriz, string, int ...
JSON.stringify({a: val1}) === JSON.stringify({a: val2})
Nota:
val1
eval2
com seu objetofonte
JSON.stringify
que uma reordenação alfabética? (Que eu não posso encontrar documentado .)Eu uso essa
comparable
função para produzir cópias dos meus objetos que são comparáveis a JSON:É útil em testes (a maioria das estruturas de teste tem uma
is
função). Por exemploSe uma diferença for detectada, as strings serão registradas, tornando as diferenças detectáveis:
fonte
Heres é uma solução no ES6 / ES2015 usando uma abordagem de estilo funcional:
demo disponível aqui
fonte
Não sei se alguém postou algo parecido com isso, mas aqui está uma função que eu fiz para verificar a igualdade de objetos.
Além disso, é recursivo, para que também possa verificar a igualdade profunda, se é assim que você chama.
fonte
Para aqueles que usam NodeJS, existe um método conveniente chamado
isDeepStrictEqual
na biblioteca Util nativa que pode conseguir isso.https://nodejs.org/api/util.html#util_util_isdeepstrictequal_val1_val2
fonte
ES6: O código mínimo que eu poderia fazer é esse. Ele faz uma comparação profunda recursivamente, restringindo todos os objetos, a única limitação é que nenhum método ou símbolo é comparado.
fonte
você pode usar a
_.isEqual(obj1, obj2)
partir da biblioteca underscore.js.Aqui está um exemplo:
Veja a documentação oficial aqui: http://underscorejs.org/#isEqual
fonte
Supondo que a ordem das propriedades no objeto não seja alterada.
JSON.stringify () funciona para ambos os tipos de objetos, profundo e não profundo, sem ter certeza dos aspectos de desempenho:
fonte
Uma solução simples para esse problema que muitas pessoas não percebem é classificar as sequências JSON (por caractere). Isso geralmente também é mais rápido do que as outras soluções mencionadas aqui:
Outra coisa útil sobre esse método é que você pode filtrar comparações passando uma função "substituta" para as funções JSON.stringify ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON / stringify # Example_of_using_replacer_parameter ). A seguir, apenas serão comparadas todas as chaves de objetos denominadas "derp":
fonte
areEqual({a: 'b'}, {b: 'a'})
ficatrue
então?Só queria contribuir com minha versão de comparação de objetos utilizando alguns recursos do es6. Não leva em consideração um pedido. Depois de converter todos os if / else para ternário, vim com o seguinte:
fonte
Precisando de uma função de comparação de objetos mais genérica do que a postada, preparei o seguinte. Crítica apreciada ...
fonte
Object.prototype
- na grande maioria dos casos, isso não é recomendado (acréscimos aparecem em todos os loops .. nos, por exemplo). Talvez considereObject.equals = function(aObj, bObj) {...}
?Se você estiver comparando objetos JSON, poderá usar https://github.com/mirek/node-rus-diff
Uso:
Se dois objetos forem diferentes, um
{$rename:{...}, $unset:{...}, $set:{...}}
objeto semelhante compatível com o MongoDB será retornado.fonte
Enfrentei o mesmo problema e decidi escrever minha própria solução. Mas como também quero comparar matrizes com objetos e vice-versa, criei uma solução genérica. Decidi adicionar as funções ao protótipo, mas é possível reescrevê-las facilmente para funções independentes. Aqui está o código:
Este algoritmo é dividido em duas partes; A função igual é uma função para encontrar o índice numérico de uma propriedade em uma matriz / objeto. A função find é necessária apenas porque o indexof localiza apenas números e seqüências de caracteres e nenhum objeto.
Pode-se chamar assim:
A função retorna true ou false, nesse caso true. O algoritmo também permite a comparação entre objetos muito complexos:
O exemplo superior retornará true, mesmo que as propriedades tenham uma ordem diferente. Um pequeno detalhe a ser observado: esse código também verifica o mesmo tipo de duas variáveis; portanto, "3" não é o mesmo que 3.
fonte
Vejo respostas do código do espaguete. Sem usar nenhuma biblioteca de terceiros, isso é muito fácil.
Primeiro, classifique os dois objetos digitando seus nomes de chave.
Em seguida, basta usar uma string para compará-los.
fonte
Eu aconselho contra hash ou serialização (como a solução JSON sugere). Se você precisar testar se dois objetos são iguais, será necessário definir o que significa igual. Pode ser que todos os membros de dados em ambos os objetos correspondam, ou pode ser que os locais da memória correspondam (ou seja, ambas as variáveis fazem referência ao mesmo objeto na memória) ou pode ser que apenas um membro de dados em cada objeto deve corresponder.
Recentemente, desenvolvi um objeto cujo construtor cria um novo ID (iniciando em 1 e incrementando em 1) cada vez que uma instância é criada. Este objeto possui uma função isEqual que compara esse valor de identificação com o valor de identificação de outro objeto e retorna true se corresponderem.
Nesse caso, defini "igual" como significando que os valores de id correspondem. Dado que cada instância tem um ID exclusivo, isso pode ser usado para reforçar a ideia de que objetos correspondentes também ocupam o mesmo local de memória. Embora isso não seja necessário.
fonte
É útil considerar dois objetos iguais se eles tiverem os mesmos valores para todas as propriedades e recursivamente para todos os objetos e matrizes aninhados. Também considero os dois objetos a seguir iguais:
Da mesma forma, matrizes podem ter elementos "ausentes" e elementos indefinidos. Eu trataria os mesmos também:
Uma função que implementa esta definição de igualdade:
Código fonte (incluindo as funções auxiliares, generalType e uniqueArray): Teste de Unidade e Teste de Execução aqui .
fonte
Estou fazendo as seguintes suposições com esta função:
Isso deve ser tratado como uma demonstração de uma estratégia simples.
fonte
Esta é uma adição a todas as opções acima, não uma substituição. Se você precisar comparar rapidamente objetos rasos sem precisar verificar casos recursivos extras. Aqui está um tiro.
Isso se compara a: 1) Igualdade de número de propriedades próprias, 2) Igualdade de nomes de chaves, 3) se bCompareValues == true, Igualdade de valores de propriedades correspondentes e seus tipos (igualdade tripla)
fonte
Para comparar chaves para instâncias simples de objetos pares de chave / valor, eu uso:
Uma vez comparadas as chaves,
for..in
basta um loop adicional simples .A complexidade é O (N * N) com N é o número de chaves.
Espero / acho que os objetos que defino não conterão mais de 1000 propriedades ...
fonte
Eu sei que isso é um pouco antigo, mas eu gostaria de adicionar uma solução que eu criei para esse problema. Eu tinha um objeto e queria saber quando seus dados foram alterados. "algo semelhante ao Object.observe" e o que eu fiz foi:
Isso aqui pode ser duplicado e criar um outro conjunto de matrizes para comparar os valores e as chaves. É muito simples porque agora são matrizes e retornará false se os objetos tiverem tamanhos diferentes.
fonte
false
, porque matrizes não se comparam por valor, por exemplo[1,2] != [1,2]
.