A great question, Rodrigo! I will answer your question by improving two of the codes already made by colleagues, also passing you some other information about JavaScript. In the end, I'll show you my own solution, uniting everything I've had.
Unfortunately, unlike some other languages, JavaScript does not have the "equals" method (like C # or Java). In addition, this language has two distinct pairs of equality operators.
=== e! ==
They function as you would normally expect; if both sides of the equality are of the same type and have the same value, then the result is true. Otherwise, it returns false.
== e! =
JavaScript will coerce value between the two sides of equality without checking the type. If they have the same value, it returns true. Otherwise, it returns false. However, one should be very careful with these, as they make a very superficial check and often you can end up with an undesirable result.
When in doubt, always use the first pair .
In both of your comparisons, the returned value was false, because what you are trying to compare is a complex object, and it has only the reference to the object stored in the variable: so the objects have different references and are < in> different objects . If they were literal values, direct comparison would be possible.
Now, for the real answer to your question: as JavaScript does not have a specific method for comparing objects, and even the best equality operators ( === and! == ) do not work with complex objects, it is necessary to make a method for comparison ourselves.
However, what are the problems with the codes above?
Code 1
This code has the unfortunate question that it does not check whether this object has, internally, other objects. So if it ends up finding an object inside the one being checked, it will check only the references (as I mentioned earlier), and the result will be false even if both are really the same. I made some comments in the code to show the problems and the qualities.
function isEquivalent(a, b) {
// Acredito que essa seja uma das qualidades do código.
// É realizada a verificação do que o objeto possui internamente, e isso
// é passado diretamente para a variável.
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
// Então, é feita a verificação se os dois objetos possuem o mesmo
// número de propriedades. Muito bom! E tira muito trabalho caso não
// tenham.
if (aProps.length != bProps.length) {
return false;
}
// Caso tenham o mesmo número, é realizada uma iteração por todas as
// propriedades do objeto. Porém, como ressaltei antes, não busca por
// objetos dentro de objetos, podendo retornar uma inconsistência.
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
if (a[propName] !== b[propName]) {
return false;
}
}
return true;
}
Code 2
Well, this code is just plain confusing. It does not make an obvious check of object properties (like the previous one did), and it uses many if, making it difficult to read and understand the code. Moreover, it uses within it equality operators that compare only the value (which can lead to inconsistencies, depending on the value compared!). However, I do not quite understand how it works. Just like in the previous one, I made some comments about the code (with what I could understand):
function deepEqual(obj1 , obj2 , profund){
// Nesse primeiro if, ele está verificando se os dois objetos são, realmente,
// objects, além de fazer a comparação obj1 != obj2, que sempre retornará false,
// a não ser que sejam valores literais e sejam iguais.
// Desnecessário.
if(typeof(obj1) == "object" && typeof(obj2)=='object' && obj1 != obj2){
// Aqui, ele pega as propriedades dos dois objetos e verifica se possuem
// a mesma quantidade, porém não as armazena em local algum.
if(Object.keys(obj1).length == Object.keys(obj2).length){
// Aqui, está realizando um for in, que passa por todas as propriedades
// do objeto, inclusive os prototype. Pode dar algum resultado errado!
for (var prop in obj1) {
if ((prop in obj2)){
// Aqui, ele realiza a comparação dos dois objetos.
if(profund == true && obj1[prop] != obj2[prop]){
return false;
break
}else if(profund == false){
return true
break
}
}
}
return true;
}
}else{
return (obj1 === obj2);
}
}
Now, finally , the code that I believe to be the best for full comparison of complex objects. I did this using some techniques I learned in Douglas Crockford's The Good Parts . Highly recommend the reading! It will be a code very much like Code 1 , but with the improvement that I believe was lacking in it. I use, for this, one of the best things created in the history of computing: recursion! Below is the code with comments.
var equals = function (object1, object2) {
// Realiza a verificação das propriedades dos objetos.
var prop1 = Object.getOwnPropertyNames(object1);
var prop2 = Object.getOwnPropertyNames(object1);
// Realiza a verificação se ambos objetos possuem o mesmo número de
// propriedades. Caso contrário, já retorna dizendo que são diferentes.
if(prop1.length !== prop2.length)
return false;
// Aqui, está sendo verificado se o objeto possui alguma propriedade.
// Será usado quando for chamada a função na sua forma recursiva,
// para verificar valores literais.
if(prop1.length === 0)
if(object1 === object2)
return true;
else
return false;
// Se forem iguais, realiza uma iteração por todas as propriedades.
for(var i = 0; i < prop1.length; i++) {
// Guarda o valor da propriedade atual na variável "prop".
var prop = prop1[i];
// Aqui está o pulo do gato.
// Verifica se o valor e o tipo das duas propriedades são iguais.
// Se sim, somente pula para a próxima iteração. Caso contrário,
// podem ser duas coisas: ou são realmente distintos, ou é um objeto,
// que, ao comparar as referências, retorna sempre falso.
// Para ter certeza da informação, é chamada a mesma função de forma
// recursiva, mandando, por parâmetro, os dois objetos que ficou a dúvida.
// Se forem iguais, ou se tiverem mais algum objeto internamente,
// a função continuará a ser chamada recursivamente, até chegar ao
// ponto de ser um valor literal. Ou, então, retornará falso, pois não
// são iguais.
// Caso sejam iguais, a função só continuará para a próxima iteração.
// Caso contrário, a função já informa que não são dois objetos iguais.
if(object1[prop] !== object2[prop]){
if(equals(object1[prop], object2[prop]))
continue;
else
return false;
}
}
// Se chegou até aqui e aguentou todas as verificações...
// Os objetos são iguais!
return true;
}
That was it for today! I hope I have helped.