0

I am storing (x,y) coordinates as 2-element arrays.

var coordinateA = [0,3];
var coordinateB = [1,2];

I also have a longer array containing many of these coordinates:

var coordinates = [coordinateA, coordinateB]

Imagine my surprise when the following statements turned out to be false:

jQuery.inArray(coordinateA, coordinates); // returns -1
coordinateA == coordinates[0];            // returns false
[0,3] == [0,3];                           // returns false(!)
coordinateA == coordinateA;               // returns true, thankfully

Could someone help me understand why this is the case? Also, is there a better way to represent 2D coordinates in Javascript? Thanks for any clues or suggestions.

nshiff
  • 192
  • 1
  • 2
  • 6
  • See [this question](http://stackoverflow.com/questions/4700085/can-i-define-custom-operator-overloads-in-javascript) for an alternative – Joe Enos Feb 09 '16 at 18:21
  • 6
    Comparing two objects determines if they are the same object, the content is not compared. – Teemu Feb 09 '16 at 18:21
  • Actually, if you set the coordinates array the way you have described, it should work as you expect (the element at `coordinates[0]`, and `coordinateA` *shoud* point to the same memory). I have a feeling the issue is somewhere else, or is browser-dependent (just confirmed it works as expected in chrome) – JCOC611 Feb 09 '16 at 18:26
  • Think of references in JS as pointers. If you have 2 `char* a, *b`, would you compare its content with `a == b`? – Derek 朕會功夫 Feb 09 '16 at 18:30

2 Answers2

4

This is because you have two separate array references.

The equality operator is checking that the references are equal, not the content of the arrays.

Jonathan.Brink
  • 23,757
  • 20
  • 73
  • 115
-1

One of the puzzling things about JavaScript is how equality is dealt with. I will do my best to explain this.

The equality rules can be quite hard to grasp. Generally speaking, you can compare by relative equality (==) or strict equality (===).

relative equality:

This compares by value only and does not care about type.

Example

var x = '2';
var y = 2;
x == y;
=> false;

In relative equality, the string "2" equals the number 2. This will return true since types are not compared

strict equality

This compares by both value and type.

Example

var x = '2';
var y = 2;
x === y;
=> false

In this case, the string "2" does NOT equal the number 2. Because String and Number are two different types.

Comparisons with arrays and objects are done differently though.

In your case, arrays are considered objects.

typeof([1,2])
=> "object"

In JavaScript, all objects are different. They are compared by their object ids. To determine if arrays are equal, you have to perform type conversion to a string.

String([1,2]) == String([1,2])
=> true

However, the underscore library has an is_equal method that can determine whether two arrays are equal

_.isEqual(array1, array2);

Underscore does this by performing a deep comparison between two objects to determine if they should be considered equal.

It's important to note that order matters here, as it does in the string comparison.

_isEqual([1,2], [1,2])
=> true

_isEqual([1,2], [2,1])
=> false
Richard Hamilton
  • 25,478
  • 10
  • 60
  • 87
  • 3
    *"relative equality - Compares by value only and does not care about type."* That's just not true. Both `==` and `===` care very much about type, and in fact the `==` cares more. When the types match, the `==` and `===` are identical, but when they don't match, the `==` does further type analysis to see if the operands can be converted to matching types, and recursively enters the algorithm until matching types are found and the values compared. –  Feb 09 '16 at 18:40
  • *"To determine if arrays are equal, you have to perform type conversion to a string."* You don't have to, and in fact it's an unreliable way of comparing: `String([1,2]) == String(["1,2"]); // true` –  Feb 09 '16 at 18:43