1

Underscore's _.indexOf method looks like this:

var nativeIndexOf = Array.prototype.indexOf;

_.indexOf = function(array, item, isSorted) {
  if (array == null) return -1;
  var i, l;
  if (isSorted) {
    i = _.sortedIndex(array, item);
    return array[i] === item ? i : -1;
  }
  if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
  for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
  return -1;
};

Toward the bottom of that method, it tries to use the native indexOf implementation, otherwise it compares the two with the identity operator ===.

The identity operator === works for primitive objects like these:

console.log("asdf" === "asdf"); // true
console.log(1 === 1); // true
console.log(1 === 1.0); // true
console.log(null === null); // true
console.log(undefined === undefined); // true

But it obviously doesn't work for two Object instances, even if they have the same properties and values:

console.log({} === {}); // false
console.log({} == {}); // false
var o = {};
console.log(o === o); // true

This makes the indexOf method not work if the items in an array are of Object type.

Question is, what's the most optimized way to find the index of an Object in an array in JavaScript. One way is to JSON.stringify(o) every item, which doesn't make sense performance wise. Another is to call toString() for every item (if toString() returns something other than [object Object], like ObjectID does in the node-native-mongodb module for node.js, returning an id string). A third solution, probably the most common, is to iterate over each key in each object. None of these are really ideal.

What is the recommended solution to this problem?

Lance
  • 75,200
  • 93
  • 289
  • 503
  • If two objects are not identical, I don't think there is a better way to find out if they're equal than comparing all their fields and their values. Well, one optimization could be to check if their prototypes are identical and then if their own fields match. – Imp May 04 '12 at 23:47
  • Of course, the previous holds depending on your definition of identity. If I have two objects: `a = {x: 0}; a.__proto__ = {y: 1};` and `b = {x: 0; y: 1}`, do you consider them identical? – Imp May 04 '12 at 23:48
  • 1
    What the best solution is will really depend on the specific use case. If a "GetId()" method can be added easily (i.e. each object already has a unique ID), that approach will most likely be the best idea. Underscore's `_.isEqual()` is a good choice if you want to compare objects. – Niko May 05 '12 at 00:04
  • 1
    answer http://stackoverflow.com/a/6689666/908879 – ajax333221 May 05 '12 at 00:53

0 Answers0