Sargis Isoyan
Sargis Isoyan

Reputation: 1089

Comparing a new Object() with another new Object() in JavaScript

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

Answers (2)

T.J. Crowder
T.J. Crowder

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:

Upvotes: 44

Thriggle
Thriggle

Reputation: 7069

The behavior is entirely as defined in the ECMAScript standards.

  1. a == b is false because they do not refer to the same object, as defined in the Abstract Equality Comparison section:

    1. 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:

    1. If x and y are the same Object value, return true.
    2. Return false.
  2. 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.

  3. a <= b is true because b < a is false, as per the old definition of the Less-than-or-equal Operator ( <= ).

    1. Let r be the result of performing abstract relational comparison rval < lval with LeftFirst equal to false. (see 11.8.5).
    2. 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

Related Questions