1

When I search for the object literal below I get for index -1 but I do not understand why.

Can I not use complex types like object literal to search for this object in the array?

var fruits = [{name: "Banana"}, {name: "Orange"}];
var index = fruits.indexOf({name: "Banana"});
HelloWorld
  • 4,671
  • 12
  • 46
  • 78
  • 2
    Objects cannot be compared in any simple way, here is a related post: http://stackoverflow.com/questions/1068834/object-comparison-in-javascript – orhanhenrik Oct 12 '14 at 22:18
  • Helpful solution to the actual problem at http://stackoverflow.com/questions/237104/array-containsobj-in-javascript – apsillers Oct 12 '14 at 22:21
  • 1
    Short answer: Because `{name: "Banana"} === {name: "Banana"}` is false. – Felix Kling Oct 12 '14 at 22:28
  • As hinted at in other comments and answers, [*Array.prototype.indexOf*](http://ecma-international.org/ecma-262/5.1/#sec-15.4.4.14) uses the [*strict equality comparison algorithm*](http://ecma-international.org/ecma-262/5.1/#sec-11.9.6) `===`, so object members will only be equal if they reference the same object. – RobG Oct 12 '14 at 22:43
  • @RobG: It wouldn't make a difference if loose comparison was used. Two objects are always compared by reference. – Felix Kling Oct 12 '14 at 23:00
  • _.some([{name: "Banana"}, {name: "Orange"}], _.isEqual.bind(this, {name: "Banana"})) – dandavis Oct 13 '14 at 00:15

2 Answers2

1

-1 means the {name: "Banana"} was not found in the array. That's because the first {name: "Banana"} is a different object from the second {name: "Banana"}.

If you were searching for a primitive type, it would work the way you are expecting. However, with an object, it looks to see that the actual objects are the same things (i.e., the same locations in memory) and not just that they have the same values.

So:

[0,1,2,3].indexOf(3);     // 3, no surprise

var foo = {name: "Banana"};
[foo].indexOf(foo);       // 0, no surprise

var bar = {name: "Banana"};
[foo].indexOf({name: "Banana"}); // -1, here's your wtf moment, 

foo is a different object than bar. They just happen to have the same properties. But they occupy different locations in memory. Or, put another way, if I modify foo, bar remains unchanged.

Lots of libraries have solved the "deep equals" issue for you, so if you're using jQuery or Underscore or something, check there. Otherwise, look up how to implement because there are some gotchas.

Trott
  • 66,479
  • 23
  • 173
  • 212
1

For multi-dimensional arrays, I don't believe you can use indexOf in such a simple way, however, you can use something like this:

for(var i = 0; i < fruits.length; i++) {
   if(fruits[i].name === 'Banana') {
     return i;
   }
}
NZ Mikey
  • 126
  • 5