3

Can someone please describe the outcome of these expressions?

  [1, 2, 4] < [1, 2, 5]  // true
  [1, 3, 4] < [1, 2, 5]  // false


  [1, 2, 3] === [1, 2, 3]   // false
  [1, 2, 3] <   [1, 2, 3]   // false
  [1, 2, 3] ==  [1, 2, 3]   // false
  [1, 2, 3] >   [1, 2, 3]   // false


  [1, 2, 3] <= [1, 2, 3]   // true
  [1, 2, 3] >= [1, 2, 3]   // true

Thanks for help and fast answer !

Smern
  • 18,746
  • 21
  • 72
  • 90
Mingebag
  • 748
  • 2
  • 20
  • 35
  • 9
    Two arrays will never be `==` or `===`, as long as they refer to different arrays (even if they look the same or have the same contents). The comparison for arrays (which are objects) is by reference, and two new arrays aren't the same reference at all. As for the `<` and `>` - I'm pretty sure the arrays are converted to string (like `[1, 2, 3]` is converted to `1,2,3`) and compared (like alphabetically) – Ian May 15 '13 at 13:47
  • @Ian but still somehow this is not logical or is it ? .. and what is with that example new Array([],null,undefined,null) == ",,,"; // true – Mingebag May 15 '13 at 13:50
  • Sure it's logical...especially for `==` and `===`. As for `<` and `>` - what would you expect to happen? – Ian May 15 '13 at 13:52
  • 1
    How many question regarding the quirks of JS comparison operators does SO need? – adrianp May 15 '13 at 13:52
  • @Mingebag, is this just musing or do you have an actual way that you want to compare certain arrays? – Smern May 15 '13 at 13:52
  • @smerny I'm just curious – Mingebag May 15 '13 at 13:55
  • @Mingebag adrianp says that because in fact there are many questions about this kind of thing. Some related questions: http://stackoverflow.com/questions/1724255/why-does-2-2-in-javascript?rq=1 http://stackoverflow.com/questions/7124884/why-does-1-2-3-4-1-23-4-in-javascript?lq=1 http://stackoverflow.com/questions/10905350/why-does-array4-in-javascript?lq=1 http://stackoverflow.com/questions/8328908/javascript-surprising-array-comparison?lq=1 – bfavaretto May 15 '13 at 14:07
  • Some more: http://stackoverflow.com/questions/13799497/why-if-is-validated-while-false-in-javascript http://stackoverflow.com/questions/359494/javascript-vs-does-it-matter-which-equal-operator-i-use http://stackoverflow.com/questions/14533046/why-doesnt-javascript-have-strict-greater-less-than-comparison-operators http://stackoverflow.com/questions/14348266/can-i-trust-elements-from-a-new-array-to-equal-to-false http://stackoverflow.com/questions/12753646/javascript-comparison-crises – bfavaretto May 15 '13 at 14:08
  • @bfavaretto why are you down voting my question and try to close it ? – Mingebag May 15 '13 at 14:10
  • 1
    I didn't downvote, and don't agree with whoever downvoted. It's not a bad question. But I voted to close because there are many other similar questions, so this can be considered a duplicate. This is not as bad as you think, you already got 5 answers, you accepted one, and the duplicate link at the top (as well as the other links on the right column) can be helpful to future visitors. The question will stay around, containing valuable answers and links to related content. – bfavaretto May 15 '13 at 14:16

4 Answers4

4

Equality =

[1, 2, 3] == [1, 2, 3]

is described under The Abstract Equality Comparison Algorithm, which basically says

(if x or y are primitives, compare them, otherwise...)
Return true if x and y refer to the same object. Otherwise, return false.

Since different object literals always represent different objects, even if the content is the same, the above comparison fails.

Relational operators < >

Relative comparisons are different from equality. When you use < or >, arrays are compared as strings.

[1, 2, 4] < [1, 2, 5] 

The Abstract Relational Comparison Algorithm converts both operands to primitives. If an operand is an object, ToPrimitive calls [[DefaultValue]] which in turn is the same as obj.valueOf().toString(). Since valueOf of an object is the object itself, the whole thing boils down to

"1,2,4" < "1,2,5"

A common assumption that arrays are compared element-wise is not true:

[10,1,3] < [101,5]  // false

Note that valueOf can be overridden to affect the behavior of relational operators:

> a = [1,2,3]
[1, 2, 3]
> a < [1,2,4]
true
> a.valueOf = function() { return 'zzz' }
function () { return 'zzz' }
> a < [1,2,4]
false
Community
  • 1
  • 1
georg
  • 211,518
  • 52
  • 313
  • 390
3

In JavaScript almost everything is an Object. There are primitive types which auto-box between primitive and Object version as needed.

When you compare Objects in JavaScript, you are actually comparing if they are the same reference(e.g point to the same memory address). Proof here

 var a = [1, 2, 3];
 b = a;
 b.push(5);
 console.log(a); // 1, 2, 3, 5

In this case a == b or a === b will yield true. If I want to compare two separate arrays, then I need to loop through them and compare element by element.

In the following case, I can use a trick though. Live demo

var x = [1, 2, 3];
var y = [1, 2, 4];
var z = [1, 2, 3];
var equals = x.join("").localeCompare(y.join("")) == 0; //x with y
var equals2 = x.join("").localeCompare(z.join("")) == 0; //x with z
document.body.innerHTML += equals + "<br />";
document.body.innerHTML += equals2 + "<br />";

In your weird case

Array([],null,undefined,null) == ",,,";

In JavaScript the == operator will perform all the type casts/conversions it can perform to check for equality. It will try to compare a String with String, at which point the left hand side, the Array will be converted to a String using a simple toString() call!

Look here, I guess the answer is now obvious.

flavian
  • 28,161
  • 11
  • 65
  • 105
  • I understand you answer and thanks allot for that but how would you explain that .. Array([],null,undefined,null) == ",,,"; // true more or less the same .. or not ? – Mingebag May 15 '13 at 13:57
  • In Array([],null,undefined,null) == ",,,"; you are comparing against string so it will be like doing Array([],null,undefined,null).join() == ",,,"; – Remo H. Jansen May 15 '13 at 14:00
  • so why it the answer true ? – Mingebag May 15 '13 at 14:04
  • 1
    `.join()` is not used to compare arrays - `.toString()` is. Not that it matters, since they end up with the same result, and `.toString()` internally calls `.join()`, but still – Ian May 15 '13 at 14:09
  • my friend that send me this strange array send now the solution on this page over here http://wtfjs.com/page/5 – Mingebag May 15 '13 at 14:19
1
[1, 2, 3] === [1, 2, 3]   // false
[1, 2, 3] ==  [1, 2, 3]   // false

Arrays are objects in JavaScript and therefore compared by reference (regardless whether with strict or typecasting equality). Two distinct (even if similar) literals always evaluate to distinct objects, which will never equal. To cite the spec,

[If both x and y are of type Object, then] return true if x and y refer to the same object. Otherwise, return false.


[1, 2, 4] < [1, 2, 5]   // true
…

JavaScript's comparison operators do always cast their arguments to primitive values (and then to strings or numbers if needed). On objects, first .valueOf() then .toString() is tried. Arrays will become stringified, and for your simple example "1,2,4" indeed is smaller than "1,2,5". It would not work for complex objects, strings that contain commata or even for [12] vs [2].

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

That's how the equality algorithm has been specified (sec 11.9.3):

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

  1. If Type(x) is the same as Type(y), then
    • [...]
    • Return true if x and y refer to the same object. Otherwise, return false.

So the following will return true and all other equality comparisons will return false

var x = [1,2,3];
return x == x;
Zeta
  • 103,620
  • 13
  • 194
  • 236