Reputation: 1089
I've created two new Objects:
var a = new Object();
var b = new Object();
and after comparing, I have got those results:
var a = new Object();
var b = new Object();
console.log(a == b); //false
console.log(a > b); //false
console.log(b > a); //false
console.log(a >= b); //true
console.log(b >= a); //true
Please explain how this happens?
Upvotes: 21
Views: 1130
Reputation: 1075905
Object references compared with ==
or !=
(or ===
or !==
) are compared based on whether they refer to the same object. If so, they're equal; if not, they're not equal.
But the relational comparison operators (>
, <
, >=
, and <=
) don't compare the references, they coerce their operands to something they can compare: Numbers or strings.
In the case of new Object()
, that coercion ends up creating a string: "[object Object]"
. And of course, "[object Object]" >= "[object Object]"
is true because they're equal.
So in effect, what you're actually doing is:
console.log(a == b); //false
console.log(String(a) > String(b)); //false
console.log(String(b) > String(a)); //false
console.log(String(a) >= String(b)); //true
console.log(String(b) >= String(a)); //true
...but note that other object types coerce differently, because objects can choose how they coerce in this situation (where the spec prefers a number over a string) by implementing/overriding valueOf
. For instance, Date
objects coerce to a number when you apply a relational operator to them if the other operand can also coerce to number. So you can reliably use dt1 > dt2
to see if dt1
represents a date/time after dt2
— but you can't use dt1 == dt2
to check if dt1
and dt2
(two separate Date
objects) have the same date/time in them, because ==
will check to see if they're the same object instead. Which leads us to this bit of amusement:
var dt1 = new Date(2016, 5, 23);
var dt2 = new Date(2016, 5, 23);
console.log(dt1 < dt2); // false
console.log(dt1 > dt2); // false
console.log(dt1 == dt2); // false!
All the gory details can be found in the specification:
Object
's toString
Upvotes: 44
Reputation: 7069
The behavior is entirely as defined in the ECMAScript standards.
a == b
is false
because they do not refer to the same object, as defined in the Abstract Equality Comparison section:
If Type(x) is the same as Type(y), then
a. Return the result of performing Strict Equality Comparison x === y.
The Strict Equality Comparison algorithm itself specifies, after all other types have been checked:
- If x and y are the same Object value, return true.
- Return false.
a < b
is false
because the abstract relational comparison algorithm first converts the operands to non-Object types via the ToPrimitive abstract operation (which in the case of Objects results in a string representation of "[object Object]"
).
Since both operands will convert to the same string value, they will be equal to each other.
a <= b
is true
because b < a
is false
, as per the old definition of the Less-than-or-equal Operator ( <= ).
- Let r be the result of performing abstract relational comparison rval < lval with LeftFirst equal to false. (see 11.8.5).
- If r is true or undefined, return false. Otherwise, return true.
Again, the abstract relational comparison operation will convert the operands into string representations "[object Object]"
which will be equal to each other, so that the b < a
comparison will evaluate to false
:
Upvotes: 6