My question itself is this:
How should two objects be correctly compared in
javascript
?
$(document).ready(function(){
function p(o){
return JSON.stringify(o)
}
function compare(o1, o2){
const r = (o1 === o2)
console.log(p(o1) + ' === ' + p(o2) + ': ' + r)
}
var a = [], b = [], c = a;
var x = {}, y = {}, z = x;
compare(a, b) // false
compare(a, c) // true
compare([], []) // false
compare({}, {}) // false
compare(99, 99) // true
compare(new Number(1), 1) // false
compare(new Number(1), new Number(1)) // false
compare(new String('o'), new String('o')) // false
compare(new String('s'), 's') // true
compare('foo', 'foo') // true
compare({'foo':'bar'}, {'foo':'bar'}) // false
compare(x, y) // false
compare(x, z) // true
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I understand well that in the previous snippet the primitiveobjetos
types return correctly :true
console.log((9 === 9)) // true
But I would like to know, in addition to knowing how to correctly compare two objects, why this happens...
console.log(([] === [])) // false
UPDATE:
The comparison of objects through JSON.stringify()
is ruled out, in the following example you can see how these two objects are the same, their only variation is the position of their elements , so when comparing them it will return false
:
var a = JSON.stringify({
"firstName": "JP",
"lastName": "Richardson"
});
var b = JSON.stringify({
"firstName": "JP",
"lastName": "Richardson"
});
console.log(a === b); // true
var x = JSON.stringify({
"firstName": "JP",
"lastName": "Richardson"
});
var y = JSON.stringify({
"lastName": "Richardson",
"firstName": "JP"
});
console.log(x === y); // false
Direct response
To compare whether two objects are "twins", first determine whether they are "children" of the same "parent" and then whether they have the same "DNA", i.e. that the objects are instances of the same object and the properties are the same ( name , order, attributes and values).
If you are not interested in them being "twins" but only some items being the same, then compare those items.
Here is a brief example on how to know if two objects are instances of the same object and, for brevity, if they have the same properties, meaning that the properties of both have the same name and that their position is the same.
Explanation
The "must" of a comparison is stated by the purpose and in the case of JavaScript even more so.
Compared to other programming languages, JavaScript could be considered very flexible since the algorithms for how operations should be performed take into account the types of the operands.
Considering the above when implementing a comparison in JavaScript we must keep in mind:
Considering the above as well as the premise of being a flexible language, JavaScript includes two types of comparisons, strict and abstract, each of which has its own algorithm, which are described in the ECMAScript specifications. Below are the links to the corresponding sections of version 5.
In summary
A strict comparison of two objects returns false because it is so specified in the specification. The logic of this is similar to the legal identity of "twins" in "Western" countries, although they have the same parents, each one is registered with a different name and each one has the rights and obligations as independent individuals according to their individual conditions. .
The result of an abstract comparison of two objects is "confusing" because it varies depending on the type of the objects.
I assume we are talking about comparing values that two objects store. In that case, what @M.Gress mentions is only valid if both objects are identical even in the order of their properties , which is not very useful. The ideal way would be to compare all properties even non-enumerable ones, but this is not possible, at least not in all browsers.
In the darkest part of JavaScript, where evil and confusion reigns, there are two groups of comparison operators:
The strict group includes the operators
===
and!==
, while the non-strict group includes -as teacher Douglas Cockford would say in his book "JavaScript: the good parts"- their evil twins==
and!=
. This last group should be avoided at all costs because they are the cause of many headaches.non-strict group
This group of equality operators should be avoided as much as possible, in fact, I would recommend that you forget about their existence. A key point to understand the source of problems when using the operators is the following: the equality comparison in JavaScript is not transitive . What does this mean? Let's see it in the following code:
Why does the comparison between
foo
andfoo3
result infalse
when they are equal values?Well, the answer is a bit tricky. To understand why this happens, we need to understand how the comparison is done internally .
What does this mean? It means the following. If you compare two variables that are not objects, if they are internally different, they are converted to numbers using
ToNumber
, and then perform a strict comparison . This is why this is true:This also applies to booleans since a boolean in decimal representation will be 0 or 1. However, something different happens when you compare a variable X with an object or two objects: here operand A or B (whichever is object) is evaluated with
ToPrimitive
, this inner method simply makes recursive calls totoString
andvalueOf
to get some primitive value. Subsequently, it makes use ofToNumber
to perform a comparison.If you compare two objects, basically the non-strict equality operator will return true when they compare the same reference in memory:
strict group
Here there are no detours, first it is verified that it is the same data type, then values are compared.
How to compare two objects?
If we talk about literal objects and comparing their own properties , it is enough to iterate the properties of both objects. For example: